chdemko/php-sorted-collections

View on GitHub
src/SortedCollection/AbstractMap.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php

/**
 * chdemko\SortedCollection\AbstractMap class
 *
 * @author    Christophe Demko <chdemko@gmail.com>
 * @copyright Copyright (C) 2012-2023 Christophe Demko. All rights reserved.
 *
 * @license BSD 3-Clause License
 *
 * This file is part of the php-sorted-collections package https://github.com/chdemko/php-sorted-collections
 */

// Declare chdemko\SortedCollection namespace
namespace chdemko\SortedCollection;

/**
 * AbstractMap
 *
 * @package    SortedCollection
 * @subpackage Map
 *
 * @since 1.0.0
 *
 * @property-read callable   $comparator  The key comparison function
 * @property-read TreeNode   $first       The first element of the map
 * @property-read mixed      $firstKey    The first key of the map
 * @property-read mixed      $firstValue  The first value of the map
 * @property-read TreeNode   $last        The last element of the map
 * @property-read mixed      $lastKey     The last key of the map
 * @property-read mixed      $lastValue   The last value of the map
 * @property-read Iterator   $keys        The keys iterator
 * @property-read Iterator   $values      The values iterator
 * @property-read integer    $count       The number of elements in the map
 */
abstract class AbstractMap implements SortedMap
{
    /**
     * Magic get method
     *
     * @param string $property The property
     *
     * @throws RuntimeException If the property does not exist
     *
     * @return mixed The value associated to the property
     *
     * @since 1.0.0
     */
    public function __get($property)
    {
        switch ($property) {
            case 'comparator':
                return $this->comparator();
            case 'firstKey':
                return $this->firstKey();
            case 'lastKey':
                return $this->lastKey();
            case 'firstValue':
                return $this->firstValue();
            case 'lastValue':
                return $this->lastValue();
            case 'first':
                return $this->first();
            case 'last':
                return $this->last();
            case 'keys':
                return $this->keys();
            case 'values':
                return $this->values();
            case 'count':
                return $this->count();
            default:
                throw new \RuntimeException('Undefined property');
        }
    }

    /**
     * Get the first key
     *
     * @return mixed The first key
     *
     * @throws OutOfBoundsException If there is no element
     *
     * @since 1.0.0
     */
    public function firstKey()
    {
        return $this->first()->key;
    }

    /**
     * Get the first value
     *
     * @return mixed The first value
     *
     * @throws OutOfBoundsException If there is no element
     *
     * @since 1.0.0
     */
    public function firstValue()
    {
        return $this->first()->value;
    }

    /**
     * Get the last key
     *
     * @return mixed The last key
     *
     * @throws OutOfBoundsException If there is no element
     *
     * @since 1.0.0
     */
    public function lastKey()
    {
        return $this->last()->key;
    }

    /**
     * Get the last value
     *
     * @return mixed The last value
     *
     * @throws OutOfBoundsException If there is no element
     *
     * @since 1.0.0
     */
    public function lastValue()
    {
        return $this->last()->value;
    }

    /**
     * Returns the greatest key lesser than the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found key
     *
     * @throws OutOfBoundsException If there is no lower element
     *
     * @since 1.0.0
     */
    public function lowerKey($key)
    {
        return $this->lower($key)->key;
    }

    /**
     * Returns the value whose key is the greatest key lesser than the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found value
     *
     * @throws OutOfBoundsException If there is no lower element
     *
     * @since 1.0.0
     */
    public function lowerValue($key)
    {
        return $this->lower($key)->value;
    }

    /**
     * Returns the greatest key lesser than or equal to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found key
     *
     * @throws OutOfBoundsException If there is no floor element
     *
     * @since 1.0.0
     */
    public function floorKey($key)
    {
        return $this->floor($key)->key;
    }

    /**
     * Returns the value whose key is the greatest key lesser than or equal to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found value
     *
     * @throws OutOfBoundsException If there is no floor element
     *
     * @since 1.0.0
     */
    public function floorValue($key)
    {
        return $this->floor($key)->value;
    }

    /**
     * Returns the key equal to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found key
     *
     * @throws OutOfBoundsException If there is no such element
     *
     * @since 1.0.0
     */
    public function findKey($key)
    {
        return $this->find($key)->key;
    }

    /**
     * Returns the value whose key equal to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found value
     *
     * @throws OutOfBoundsException If there is no such element
     *
     * @since 1.0.0
     */
    public function findValue($key)
    {
        return $this->find($key)->value;
    }

    /**
     * Returns the lowest key greater than or equal to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found key
     *
     * @throws OutOfBoundsException If there is no ceiling element
     *
     * @since 1.0.0
     */
    public function ceilingKey($key)
    {
        return $this->ceiling($key)->key;
    }

    /**
     * Returns the value whose key is the lowest key greater than or equal to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found value
     *
     * @throws OutOfBoundsException If there is no ceiling element
     *
     * @since 1.0.0
     */
    public function ceilingValue($key)
    {
        return $this->ceiling($key)->value;
    }

    /**
     * Returns the lowest key greater than to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found key
     *
     * @throws OutOfBoundsException If there is no higher element
     *
     * @since 1.0.0
     */
    public function higherKey($key)
    {
        return $this->higher($key)->key;
    }

    /**
     * Returns the value whose key is the lowest key greater than to the given key
     *
     * @param mixed $key The searched key
     *
     * @return mixed The found value
     *
     * @throws OutOfBoundsException If there is no higher element
     *
     * @since 1.0.0
     */
    public function higherValue($key)
    {
        return $this->higher($key)->value;
    }

    /**
     * Keys iterator
     *
     * @return Iterator The keys iterator
     *
     * @since 1.0.0
     */
    public function keys()
    {
        return Iterator::keys($this);
    }

    /**
     * Values iterator
     *
     * @return Iterator The values iterator
     *
     * @since 1.0.0
     */
    public function values()
    {
        return Iterator::values($this);
    }

    /**
     * Convert the object to a string
     *
     * @return string String representation of the object
     *
     * @since 1.0.0
     */
    public function __toString()
    {
        return json_encode($this->toArray());
    }

    /**
     * Convert the object to an array
     *
     * @return array Array representation of the object
     *
     * @since 1.0.0
     */
    public function toArray()
    {
        $array = array();

        foreach ($this as $key => $value) {
            $array[$key] = $value;
        }

        return $array;
    }

    /**
     * Create an iterator
     *
     * @return Iterator A new iterator
     *
     * @since 1.0.0
     */
    public function getIterator(): Iterator
    {
        return Iterator::create($this);
    }

    /**
     * Get the value for a key
     *
     * @param mixed $key The key
     *
     * @return mixed The found value
     *
     * @throws OutOfRangeException If there is no such element
     *
     * @since 1.0.0
     */
    public function offsetGet($key): mixed
    {
        try {
            return $this->find($key)->value;
        } catch (\OutOfBoundsException $e) {
            throw new \OutOfRangeException('Undefined offset');
        }
    }

    /**
     * Test the existence of a key
     *
     * @param mixed $key The key
     *
     * @return boolean TRUE if the key exists, false otherwise
     *
     * @since 1.0.0
     */
    public function offsetExists($key): bool
    {
        try {
            return (bool) $this->find($key);
        } catch (\OutOfBoundsException $e) {
            return false;
        }
    }

    /**
     * Set the value for a key
     *
     * @param mixed $key   The key
     * @param mixed $value The value
     *
     * @return void
     *
     * @throws RuntimeOperation The operation is not supported by this class
     *
     * @since 1.0.0
     */
    public function offsetSet($key, $value): void
    {
        throw new \RuntimeException('Unsupported operation');
    }

    /**
     * Unset the existence of a key
     *
     * @param mixed $key The key
     *
     * @return void
     *
     * @throws RuntimeOperation The operation is not supported by this class
     *
     * @since 1.0.0
     */
    public function offsetUnset($key): void
    {
        throw new \RuntimeException('Unsupported operation');
    }
}