<?php

require_once 'common/bean/Bean.php';

/**
 * Class that encapsulates a TokenMap array.
 * 
 * This class holds a Bean that has the ability to transform in a string 
 * the token composed of this parts, and also do the reverse work.
 * Internally, it allways use a Collection. So, if you need a Collection, use 
 * $this; if need a string, use implode(). If you enter a Collection, use the 
 * constructor, or putAll(); if enter a string, use explode (constructor also 
 * supports it internally).
 * Both implode() and explode() can receive an extra parameter, allowing this
 * class to be used statically.
 * Works as container (when you create an instance) or transformer (when used
 * statically).
 * When you extend this class, you need to implement two abstract methods that 
 * performs the real work.
 * 
 * Diagram of possible uses:<pre>
 *  input arr -> __contruct()
 *  input str -> __contruct() + explode (str2arr)
 *  output arr -> $this
 *  output str -> implode (arr2str)
 * </pre>
 * 
 * @todo Could work also as "merger". See Bean's utils merge() and copy()
 * @todo Extend to DSN, URL, etc.
 * 
 * @todo Static use of this method isn't working due to documented feature that 
 * says that static methods can't call methods from child classes. I had opened 
 * a Change Request about it. Track it at http://bugs.php.net/38081
 * For more info, see: http://www.php.net/manual/en/language.oop5.static.php
 * 
 * @abstract
 * @implements ICollection, IIterable
 * @author  $Author: pruna $
 * @package common/collection
 * @version $Revision: 1.1 $
 * @created 04-Aug-2004
 * @modified $Date: 2005/12/06 02:56:45 $
 */
abstract class TokenMap extends Bean {
    
    /**
     * Constructor for TokenMap. All children should call it.
     * Set values, and then adds required keys and default values.
     * Atention! This class adds string support to constructor, modifing
     * default behavoir (cast string to 1 element Collection).
     *
     * @access    public
     * @param     mixed    $input    Collection or string to tokenize
     */
    public function __construct($input = null) {
        parent::__construct($this->getDefaultValues());
        if (is_string($input)) {
            $this->explode($input);
        } else {
            parent::setAll($input);
        }
    }
    
    /**
     * Joins $obj elements and returns it as an string.
     * 
     * @abstract
     * @access    protected
     * @param     HashMap    $obj     Object to recompose to string
     * @return    string
     */
    abstract protected function arr2str($obj);
    
    /**
     * Splits elements and returns it as a Collection - str2arr.
     * If second parameter is given, it returns a Collection, else saves it.
     * It should follow the specific rules for the given token.
     * 
     * @access    public
     * @param     string    $string     String to explode
     * @param     mixed     $return     Collection, or boolean, to return data
     * @return    array
     */
    public function explode($string, $return = FALSE) {
        if ($return === TRUE) {
            return self::str2arr($string, new HashMap());
        } elseif ($return) {
            return self::str2arr($string, $return);
        } else {
            return $this->str2arr($string, $this);
        }
    }
    
    /**
     * Returns a Collection with required keys and default values.
     * 
     * @abstract
     * @access	protected
     * @return	Collection
     */
    abstract protected function getDefaultValues();
    
    /**
     * Joins elements and returns it as an string - arr2str.
     * It should follow the specific rules for the given token.
     * 
     * @access    public
     * @param     ICollection    $collection     Optional to use static
     * @return    string
     */
    public function implode($collection = null) {
        if (!is_null($collection)) {
            return self::arr2str($collection);
        } else {
            return $this->arr2str($this);
        }
    }
    
    /**
     * Splits $str elements and returns it in $obj.
     * 
     * @abstract
     * @access    protected
     * @param     string     $str     String to decompose to HashMap
     * @param     HashMap    $obj     HashMap to modify
     * @return    string
     */
    abstract protected function str2arr($str, $obj);
    
}

?>