array("label"=>"Normal"), self::SET_BEHAVIOUR_IGNORE => array("label"=>"Ignore"), self::SET_BEHAVIOUR_THROW => array("label"=>"Throw Exception") ); public static $UNSET_BEHAVIOURS = array( self::UNSET_BEHAVIOUR_NORMAL => array("label"=>"Normal"), self::UNSET_BEHAVIOUR_IGNORE => array("label"=>"Ignore"), self::UNSET_BEHAVIOUR_THROW => array("label"=>"Throw Exception") ); public static $GET_BEHAVIOURS = array( self::GET_BEHAVIOUR_NORMAL => array("label"=>"Normal"), self::GET_BEHAVIOUR_EMPTY => array("label"=>"Empty"), self::GET_BEHAVIOUR_THROW => array("label"=>"Throw Exception") ); private $constraints = array(); public function __construct(){ $this->createSetBehaviour("*", self::SET_BEHAVIOUR_NORMAL); $this->createGetBehaviour("*", self::GET_BEHAVIOUR_NORMAL); $this->createUnsetBehaviour("*", self::UNSET_BEHAVIOUR_NORMAL); } public function createSetBehaviour($key, $behaviour, ConstrainedBehaviour $callbackClass = null){ // if (strpos($key, ".")!== false){ // $matches = array(); // if (!preg_match("/^([^.]+)\.(.+)$/", $key, $matches)){ // throw new CoreException("Invalid key format passed to ".get_class($this)."::createSetBehaviour ($key)"); // } // $myKey = $matches[1]; // $childKey = $matches[2]; // $child = $this->getInternal($myKey); // if (is_null($child)){ // $this->setInternal($myKey, new ConstrainedMemoryObject()); // } // if ($child instanceof Constrained){ // $child->createSetBehaviour($childKey, $behaviour, $callbackClass); // } // else { // throw new CoreException("Invalid key passed to ".get_class($this)."::createSetBehaviour. Setting a child constraint on a non constrained element."); // } // } // else { if (!array_key_exists($behaviour, self::$SET_BEHAVIOURS)){ throw new CoreException("Invalid behaviour parameter passed to ".get_class($this)."::createSetBehaviour ($behaviour)"); } if (!array_key_exists($key,$this->constraints)){ $this->constraints[$key] = new stdClass(); } $this->constraints[$key]->set = new stdClass(); $this->constraints[$key]->set->behaviour = $behaviour; $this->constraints[$key]->set->callbackClass = $callbackClass; // } } public function createGetBehaviour($key, $behaviour, ConstrainedBehaviour $callbackClass = null){ if (!array_key_exists($behaviour, self::$GET_BEHAVIOURS)){ throw new CoreException("Invalid behaviour parameter passed to ".get_class($this)."::createGetBehaviour ($behaviour)"); } if (!array_key_exists($key,$this->constraints)){ $this->constraints[$key] = new stdClass(); } $this->constraints[$key]->get = new stdClass(); $this->constraints[$key]->get->behaviour = $behaviour; $this->constraints[$key]->get->callbackClass = $callbackClass; } public function createUnsetBehaviour($key, $behaviour, ConstrainedBehaviour $callbackClass = null){ if (!array_key_exists($behaviour, self::$UNSET_BEHAVIOURS)){ throw new CoreException("Invalid behaviour parameter passed to ".get_class($this)."::createUnsetBehaviour ($behaviour)"); } if (!array_key_exists($key,$this->constraints)){ $this->constraints[$key] = new stdClass(); } $this->constraints[$key]->unset = new stdClass(); $this->constraints[$key]->unset->behaviour = $behaviour; $this->constraints[$key]->unset->callbackClass = $callbackClass; } public function setConstrained($key, $value){ try { $constraint = $this->constraints["*"]->set; if (array_key_exists($key, $this->constraints) && property_exists($this->constraints[$key], "set")){ $constraint = $this->constraints[$key]->set; } $constraint = $this->constraints[$key]->set; switch ($constraint->behaviour){ case self::SET_BEHAVIOUR_NORMAL: $this->setInternal($key, $value); break; case self::SET_BEHAVIOUR_THROW: throw new ConstraintException("set",$key,$value); break; case self::SET_BEHAVIOUR_IGNORE: default: break; } if (property_exists($constraint, "callbackClass") && !is_null($constraint->callbackClass)){ $this->setBase($constraint->callbackClass->executeSetCallback($this->getBase(), $key, $value)); } } catch (ConstraintException $cex){ throw $this->addPathToChildException($cex); } } public function getConstrained($key){ try { $rval = null; if (array_key_exists($key, $this->constraints) && property_exists($this->constraints[$key], "get")){ $constraint = $this->constraints[$key]->get; switch ($constraint->behaviour){ case self::GET_BEHAVIOUR_THROW: throw new ConstraintException("get",$key); break; case self::GET_BEHAVIOUR_NORMAL: $rval = $this->getInternal($key); break; case self::GET_BEHAVIOUR_EMPTY: default: break; } if (property_exists($constraint, "callbackClass") && !is_null($constraint->callbackClass)){ $rval = $constraint->callbackClass->executeGetCallback($this->getBase(), $key); } } else { $rval = $this->getInternal($key); } return $rval; } catch (ConstraintException $cex){ throw $this->addPathToChildException($cex); } } public function unsetConstrained($key){ try { if (array_key_exists($key, $this->constraints) && property_exists($this->constraints[$key], "unset")){ $constraint = $this->constraints[$key]->unset; switch ($constraint->behaviour){ case self::UNSET_BEHAVIOUR_NORMAL: $this->unsetInternal($key); break; case self::UNSET_BEHAVIOUR_THROW: throw new ConstraintException("unset",$key); break; case self::UNSET_BEHAVIOUR_IGNORE: default: break; } if (property_exists($constraint, "callbackClass") && !is_null($constraint->callbackClass)){ $this->setBase($constraint->callbackClass->executeUnsetCallback($this->getBase(), $key)); } } else { $this->unsetInternal($key); } } catch (ConstraintException $cex){ throw $this->addPathToChildException($cex); } } protected function replicateConstraints(Constrained $oth){ $this->constraints = clone $oth->constraints; } protected abstract function addPathToChildException($myKey, ConstraintException $ex); protected abstract function setInternal($key,$value); protected abstract function getInternal($key); protected abstract function unsetInternal($key); protected abstract function setBase($base); } ?>