/**
  * @internal
  *
  * Used internally to parse the Model from it's model file
  *
  * @return void
  */
 protected function parse()
 {
     $xmlModels = simplexml_load_file($this->modelFile()->path()->stringValue());
     if (!$this->version()) {
         $this->version = S((string) $xmlModels->{'current-version'});
     }
     $model = null;
     foreach ($xmlModels->model as $m) {
         if (S((string) $m['version'])->equals($this->version())) {
             $model = $m;
         }
     }
     if ($model != null) {
         $relationshipsToLink = new MMutableDictionary();
         foreach ($model->entity as $entity) {
             $newEntity = new MEntityDescription(S((string) $entity['name']), S((string) $entity['plural']), S((string) $entity['class']));
             foreach ($entity->property as $property) {
                 $newProperty = new MEntityDescriptionProperty($newEntity, S((string) $property['name']));
                 if ((string) $property['type'] != null) {
                     $newProperty->setType((string) $property['type']);
                 }
                 if ((string) $property['defaultValue'] != null) {
                     $defaultValue = null;
                     if ($newProperty->type() == MEntityDescriptionProperty::StringType) {
                         $defaultValue = new MString((string) $property['defaultValue']);
                     } else {
                         if ($newProperty->type() == MEntityDescriptionProperty::IntegerType) {
                             $defaultValue = MNumber::parseInt((string) $property['defaultValue']);
                         } else {
                             if ($newProperty->type() == MEntityDescriptionProperty::FloatType) {
                                 $defaultValue = MNumber::parseFloat((string) $property['defaultValue']);
                             } else {
                                 if ($newProperty->type() == MEntityDescriptionProperty::BooleanType) {
                                     $defaultValue = MNumber::parseBool((string) $property['defaultValue']);
                                 } else {
                                     if ($newProperty->type() == MEntityDescriptionProperty::DateType) {
                                         $defaultValue = MDate::parseString((string) $property['defaultValue']);
                                     } else {
                                         if ($newProperty->type() == MEntityDescriptionProperty::BinaryType) {
                                             // BinaryType's defaultValue is ignored, always null
                                         } else {
                                             throw new MModelParseErrorException($this->modelFile(), Sf("Invalid data type '%s'", $newProperty->type()));
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     $newProperty->setDefaultValue($defaultValue);
                 }
             }
             foreach ($entity->relationship as $relationship) {
                 $newRelationship = new MEntityDescriptionRelationship($newEntity, S((string) $relationship['name']), S((string) $relationship['type']));
                 $newRelationship->setSingular(S((string) $relationship['singular']));
                 if (strtolower((string) $relationship['to']) == "many") {
                     $newRelationship->setTo(MEntityDescriptionRelationship::ToMany);
                 } else {
                     $newRelationship->setTo(MEntityDescriptionRelationship::ToOne);
                 }
                 if ($relationship['inverse'] != null) {
                     $relationshipsToLink->setObjectForKey($newRelationship, S((string) $relationship['inverse']));
                 }
             }
             $this->addEntity($newEntity);
         }
         // Link relationships to their respective inverse relationships
         foreach ($relationshipsToLink->allKeys()->toArray() as $relationship) {
             $inverse = $relationshipsToLink->objectForKey($relationship);
             $inverseEntity = $this->entityWithName($relationship->type());
             if ($inverseEntity) {
                 $inverseRelationship = $inverseEntity->attributeWithName($inverse);
                 if ($inverseRelationship) {
                     $relationship->setInverseRelationship($inverseRelationship);
                 } else {
                     throw new MModelParseErrorException($this->modelFile(), Sf("Could not find the relationship named '%s' in entity '%s'", $inverse, $relationship->type()));
                 }
             } else {
                 throw new MModelParseErrorException($this->modelFile(), Sf("[%s->%s] Inverse relationship's entity named '%s' not defined in this model version", $relationship->entity()->name(), $relationship->name(), $relationship->type()));
             }
         }
     } else {
         throw new MModelVersionNotFoundException($this->modelFile());
     }
 }
 /**
  * Returns a Managed Object whose property matches the specified object value
  *
  * This method fetches an object from the Persistent Store that contains the
  * specified property and whose value for that property matches the value
  * specified in $value
  *
  * @param MEntityDescriptionProperty $property The property whose value you
  * wish to match against
  * @param MObject $value The value to be matched
  *
  * @return MManagedObject The fetched MManagedObject
  */
 public function objectWith(MEntityDescriptionProperty $property, MObject $value = null)
 {
     $request = new MFetchRequest($property->entity(), $this);
     if ($value) {
         $request->setPredicate(Sf("%s = '%s'", $property->name()->stringValue(), $value->toString()->stringValue()));
     } else {
         $request->setPredicate(Sf("%s = null", $property->name()->stringValue()));
     }
     $data = $this->executeFetchRequest($request);
     return $data->lastObject();
 }