<commit_before><?php

namespace Minime\Annotations;

use Minime\Annotations\Interfaces\ParserRulesInterface;

/**
 *
 * An annotation collection class.
 *
 * @package Annotations
 *
 */
class AnnotationsBag implements \IteratorAggregate, \Countable, \ArrayAccess, \JsonSerializable
{

    /**
     * Associative arrays of annotations
     * @var array
     */
    private $attributes = [];

    /**
     * The ParserRules object
     * @var ParserRulesInterface
     */
    private $rules;

    /**
     * The Constructor
     * @param array                $attributes
     * @param ParserRulesInterface $rules
     */
    public function __construct(array $attributes, ParserRulesInterface $rules)
    {
        $this->rules = $rules;
        $this->replace($attributes);
    }


    public function replace(array $attributes)
    {
        foreach (array_keys($attributes) as $key) {
            if ($this->rules->isKeyValid($key)) {
                $this->attributes[$key] = $attributes[$key];
            }            
        }
        
        return $this;
    }

    /**
     * Unbox all annotations in the form of an associative array
     * @return array associative array of annotations
     */
    public function export()
    {
        return $this->attributes;
    }

    /**
     * Checks if a given annotation is declared
     * @param string $key A valid annotation tag, should match parser rules
     *
     * @throws \InvalidArgumentException If non string key is passed
     *
     * @return boolean
     */
    public function has($key)
    {
        if (! $this->rules->isKeyValid($key)) {
            throw new \InvalidArgumentException('Annotation key must be a valid annotation name string, according to parser rules.');
        }

        return array_key_exists($key, $this->attributes);
    }

    /**
     * Retrieves a single annotation value
     * @param string $key A valid annotation tag, should match parser rules
     *
     * @return mixed|null
     */
    public function get($key)
    {
        if ($this->has($key)) {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Retrieve annotation values as an array even if there's only one single value
     *
     * @return array
     */
    public function getAsArray($key)
    {
        if (! $this->has($key)) {
            return [];
        }
        $res = $this->attributes[$key];
        if (is_null($res)) {
            return [null];
        }

        return (array) $res;
    }

    /**
     * Filters annotations based on a regexp
     * @param  string                            $pattern Valid regexp
     * @throws \InvalidArgumentException         If non valid regexp is passed
     * @return Minime\Annotations\AnnotationsBag Annotations collection with filtered results
     */
    public function grep($pattern)
    {
        if (! is_string($pattern)) {
            throw new \InvalidArgumentException('Grep pattern must be a valid regexp string.');
        }

        $results = array_intersect_key(
            $this->attributes,
            array_flip(
                preg_grep('/'.$pattern.'/', array_keys($this->attributes))
            )
        );

        return new static($results, $this->rules);
    }

    /**
     * Just an alias for AnnotationsBag::useNamespace.
     *
     * @todo Remove this method in version 2.*
     * @deprecated
     * @param string $pattern namespace
     *
     * @return Minime\Annotations\AnnotationsBag
     */
    public function grepNamespace($pattern)
    {
        return $this->useNamespace($pattern);
    }

    /**
     * Isolates a given namespace of annotations.
     * @param string $pattern namespace
     *
     * @return Minime\Annotations\AnnotationsBag
     */
    public function useNamespace($pattern)
    {
        $pattern = trim($pattern);
        if (!$this->rules->isNamespaceValid($pattern))
        {
            throw new \InvalidArgumentException('Namespace pattern must be a valid namespace string, according to parser rules.');
        }
        $namespaceIdentifier = $this->rules->getNamespaceIdentifier();
        $length = strlen($pattern);
        if ($namespaceIdentifier != $pattern[$length-1])
        {
            $pattern .= $namespaceIdentifier;
            $length++;
        }
        $results = [];
        foreach ($this->attributes as $key => $value)
        {
            if (strpos($key, $pattern) === 0)
            {
                $results[substr($key, $length)] = $value;
            }
        }

        return new static($results, $this->rules);
    }

    /**
     * Merge instances of AnnotationsBag
     * @param  AnnotationsBag $bag The annotation bag to be merged
     * @return self
     */
    public function merge(AnnotationsBag $bag)
    {   
        return new static($bag->export() + $this->attributes, $this->rules);
    }

    /**
    * Countable
    */
    public function count()
    {
        return count($this->attributes);
    }

    /**
     * JsonSerializable
     */
    public function jsonSerialize() {
        return $this->export();
    }

    /**
    * IteratorAggregate<commit_msg>bug fix the merge method<commit_after><?php

namespace Minime\Annotations;

use Minime\Annotations\Interfaces\ParserRulesInterface;

/**
 *
 * An annotation collection class.
 *
 * @package Annotations
 *
 */
class AnnotationsBag implements \IteratorAggregate, \Countable, \ArrayAccess, \JsonSerializable
{

    /**
     * Associative arrays of annotations
     * @var array
     */
    private $attributes = [];

    /**
     * The ParserRules object
     * @var ParserRulesInterface
     */
    private $rules;

    /**
     * The Constructor
     * @param array                $attributes
     * @param ParserRulesInterface $rules
     */
    public function __construct(array $attributes, ParserRulesInterface $rules)
    {
        $this->rules = $rules;
        $this->replace($attributes);
    }


    public function replace(array $attributes)
    {
        foreach (array_keys($attributes) as $key) {
            if ($this->rules->isKeyValid($key)) {
                $this->attributes[$key] = $attributes[$key];
            }            
        }
        
        return $this;
    }

    /**
     * Unbox all annotations in the form of an associative array
     * @return array associative array of annotations
     */
    public function export()
    {
        return $this->attributes;
    }

    /**
     * Checks if a given annotation is declared
     * @param string $key A valid annotation tag, should match parser rules
     *
     * @throws \InvalidArgumentException If non string key is passed
     *
     * @return boolean
     */
    public function has($key)
    {
        if (! $this->rules->isKeyValid($key)) {
            throw new \InvalidArgumentException('Annotation key must be a valid annotation name string, according to parser rules.');
        }

        return array_key_exists($key, $this->attributes);
    }

    /**
     * Retrieves a single annotation value
     * @param string $key A valid annotation tag, should match parser rules
     *
     * @return mixed|null
     */
    public function get($key)
    {
        if ($this->has($key)) {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Retrieve annotation values as an array even if there's only one single value
     *
     * @return array
     */
    public function getAsArray($key)
    {
        if (! $this->has($key)) {
            return [];
        }
        $res = $this->attributes[$key];
        if (is_null($res)) {
            return [null];
        }

        return (array) $res;
    }

    /**
     * Filters annotations based on a regexp
     * @param  string                            $pattern Valid regexp
     * @throws \InvalidArgumentException         If non valid regexp is passed
     * @return Minime\Annotations\AnnotationsBag Annotations collection with filtered results
     */
    public function grep($pattern)
    {
        if (! is_string($pattern)) {
            throw new \InvalidArgumentException('Grep pattern must be a valid regexp string.');
        }

        $results = array_intersect_key(
            $this->attributes,
            array_flip(
                preg_grep('/'.$pattern.'/', array_keys($this->attributes))
            )
        );

        return new static($results, $this->rules);
    }

    /**
     * Just an alias for AnnotationsBag::useNamespace.
     *
     * @todo Remove this method in version 2.*
     * @deprecated
     * @param string $pattern namespace
     *
     * @return Minime\Annotations\AnnotationsBag
     */
    public function grepNamespace($pattern)
    {
        return $this->useNamespace($pattern);
    }

    /**
     * Isolates a given namespace of annotations.
     * @param string $pattern namespace
     *
     * @return Minime\Annotations\AnnotationsBag
     */
    public function useNamespace($pattern)
    {
        $pattern = trim($pattern);
        if (!$this->rules->isNamespaceValid($pattern))
        {
            throw new \InvalidArgumentException('Namespace pattern must be a valid namespace string, according to parser rules.');
        }
        $namespaceIdentifier = $this->rules->getNamespaceIdentifier();
        $length = strlen($pattern);
        if ($namespaceIdentifier != $pattern[$length-1])
        {
            $pattern .= $namespaceIdentifier;
            $length++;
        }
        $results = [];
        foreach ($this->attributes as $key => $value)
        {
            if (strpos($key, $pattern) === 0)
            {
                $results[substr($key, $length)] = $value;
            }
        }

        return new static($results, $this->rules);
    }

    /**
     * Merge instances of AnnotationsBag
     * @param  AnnotationsBag $bag The annotation bag to be merged
     * @return self
     */
    public function merge(AnnotationsBag $bag)
    {   
        return new static($this->attributes + $bag->export(), $this->rules);
    }

    /**
    * Countable
    */
    public function count()
    {
        return count($this->attributes);
    }

    /**
     * JsonSerializable
     */
    public function jsonSerialize() {
        return $this->export();
    }

    /**
    * IteratorAggregate
{'fraction_non_alphanumeric': 0.11385419692128958, 'fraction_numerical': 0.0005808887598024978, 'mean_word_length': 1.9371623542792153, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5438834', 'n_tokens_mistral': 2778, 'n_tokens_neox': 2695, 'n_words': 733}