      1: <?php
      2: /**
      3:  * Copyright 2012-2014 Rackspace US, Inc.
      4:  *
      5:  * Licensed under the Apache License, Version 2.0 (the "License");
      6:  * you may not use this file except in compliance with the License.
      7:  * You may obtain a copy of the License at
      8:  *
      9:  * http://www.apache.org/licenses/LICENSE-2.0
     10:  *
     11:  * Unless required by applicable law or agreed to in writing, software
     12:  * distributed under the License is distributed on an "AS IS" BASIS,
     13:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14:  * See the License for the specific language governing permissions and
     15:  * limitations under the License.
     16:  */
     17:
     18: namespace OpenCloud\Image\Resource\Schema;
     19:
     20: use OpenCloud\Image\Enum\OperationType;
     21: use OpenCloud\Image\Enum\Schema as SchemaEnum;
     22:
     23: /**
     24:  * Class that represents a JSON schema document
     25:  *
     26:  * @package OpenCloud\Images\Resource\Schema
     27:  */
     28: class Schema extends AbstractSchemaItem
     29: {
     30:     /** @var string Name of schema */
     31:     protected $name;
     32:
     33:     /** @var array Properties that this schema possesses */
     34:     protected $properties;
     35:
     36:     /**
     37:      * If set, this determines the template that all additional (i.e. undefined) properties must adhere to
     38:      *
     39:      * @var null|Property
     40:      */
     41:     protected $additionalProperties;
     42:
     43:     /** @var array Links for this schema */
     44:     protected $links;
     45:
     46:     /**
     47:      * @param array $data
     48:      * @return Schema
     49:      */
     50:     public static function factory(array $data)
     51:     {
     52:         $schema = new self();
     53:
     54:         $schema->setName(self::stockProperty($data, SchemaEnum::NAME));
     55:
     56:         if (isset($data[SchemaEnum::LINKS])) {
     57:             $schema->setLinks($data[SchemaEnum::LINKS]);
     58:         }
     59:
     60:         if (isset($data[SchemaEnum::PROPERTIES])) {
     61:             $schema->setProperties($data[SchemaEnum::PROPERTIES]);
     62:         }
     63:
     64:         if (isset($data[SchemaEnum::ADDITIONAL_PROPERTIES])) {
     65:             $schema->setAdditionalProperties($data[SchemaEnum::ADDITIONAL_PROPERTIES]);
     66:         }
     67:
     68:         return $schema;
     69:     }
     70:
     71:     /**
     72:      * @param string $name
     73:      */
     74:     public function setName($name)
     75:     {
     76:         $this->name = $name;
     77:     }
     78:
     79:     /**
     80:      * @return string
     81:      */
     82:     public function getName()
     83:     {
     84:         return $this->name;
     85:     }
     86:
     87:     /**
     88:      * @param array $properties
     89:      */
     90:     public function setProperties(array $properties)
     91:     {
     92:         foreach ($properties as $name => $array) {
     93:             $array[SchemaEnum::NAME] = $name;
     94:             $this->properties[$name] = Property::factory($array);
     95:         }
     96:     }
     97:
     98:     /**
     99:      * @return array
    100:      */
    101:     public function getProperties()
    102:     {
    103:         return $this->properties;
    104:     }
    105:
    106:     /**
    107:      * @param array $properties
    108:      */
    109:     public function setAdditionalProperties(array $properties)
    110:     {
    111:         $this->additionalProperties = $properties;
    112:     }
    113:
    114:     /**
    115:      * @return bool|Property
    116:      */
    117:     public function getAdditionalProperties()
    118:     {
    119:         if (!empty($this->additionalProperties)) {
    120:             return Property::factory($this->additionalProperties);
    121:         }
    122:
    123:         return false;
    124:     }
    125:
    126:     /**
    127:      * @param array $links
    128:      */
    129:     public function setLinks(array $links)
    130:     {
    131:         $this->links = $links;
    132:     }
    133:
    134:     /**
    135:      * @return array
    136:      */
    137:     public function getLinks()
    138:     {
    139:         return $this->links;
    140:     }
    141:
    142:     /**
    143:      * Check whether a property exists
    144:      *
    145:      * @param $property The name of the property
    146:      * @return bool
    147:      */
    148:     public function propertyExists($property)
    149:     {
    150:         return isset($this->properties[$property]);
    151:     }
    152:
    153:     /**
    154:      * Retrieve a property
    155:      *
    156:      * @param $property The name of the property
    157:      * @return null|Property
    158:      */
    159:     public function getProperty($property)
    160:     {
    161:         return $this->propertyExists($property) ? $this->properties[$property] : null;
    162:     }
    163:
    164:     /**
    165:      * Based on this schema, decide the most appropriate operation type for a given property
    166:      *
    167:      * @param Property $property The property being performed on
    168:      * @return string
    169:      */
    170:     public function decideOperationType(Property $property)
    171:     {
    172:         $name = $property->getName();
    173:
    174:         return ($this->propertyExists($name)) ? OperationType::REPLACE : OperationType::ADD;
    175:     }
    176:
    177:     /**
    178:      * Check whether an additional property is allowed and its type is valid
    179:      *
    180:      * @param $value         The value trying to be set
    181:      * @return bool|Property
    182:      */
    183:     public function validateAdditionalProperty($value)
    184:     {
    185:         if ($property = $this->getAdditionalProperties()) {
    186:             $property->setValue($value);
    187:
    188:             return ($property->validate() === true) ? $property : false;
    189:         }
    190:
    191:         return false;
    192:     }
    193: }
    194: