@param string $class

@throws \Exception

@return RelationshipEntityMetadata
556939
public function getRelationshipEntityMetadata($class)
    {
        if (!array_key_exists($class, $this->loadedMetadata)) {
            $metadata = $this->metadataFactory->create($class);
            if (!$metadata instanceof RelationshipEntityMetadata) {
                // $class is not an relationship entity
                throw new MappingException(sprintf('The class "%s" was configured to be an RelationshipEntity but no @OGM\RelationshipEntity class annotation was found', $class));
            }
            $this->loadedMetadata[$class] = $metadata;
        }

        return $this->loadedMetadata[$class];
    }
1090301
public function loadMetadataForClass(\ReflectionClass $class)
    {
        $classMetadata                  = new MergeableClassMetadata($name = $class->name);
        $classMetadata->fileResources[] = $class->getFileName();

        foreach ($class->getProperties() as $property) {
            $propertyMetadata = new PropertyMetadata($name, $property->getName());
            $propertyAnnotations = $this->reader->getPropertyAnnotations($property);

            foreach ($propertyAnnotations as $annotation) {
                if ($annotation instanceof Fixture\Data) {
                    $propertyMetadata->staticData = $annotation->value;
                } elseif ($annotation instanceof Fixture\Faker) {
                    $propertyMetadata->fakerName = $annotation->name;
                    $propertyMetadata->fakerResolverType = $annotation->type;
                    $propertyMetadata->fakerResolverArgs = $annotation->arguments;
                } elseif ($annotation instanceof Fixture\Ignore) {
                    $propertyMetadata->ignore = true;
                }
            }

            $classMetadata->addPropertyMetadata($propertyMetadata);
        }

        return $classMetadata;
    }
440945
private function executeUpdates($class)
    {
        $className        = $class->getClassName();
        $persister        = $this->getEntityPersister($className);
        $preUpdateInvoke  = $this->listenersInvoker->getSubscribedSystems($class, Events::preUpdate);
        $postUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postUpdate);

        foreach ($this->entityUpdates as $oid => $entity) {
            if ($this->em->getClassMetadata(get_class($entity))->getClassName() !== $className) {
                continue;
            }

            if ($preUpdateInvoke !== ListenersInvoker::INVOKE_NONE) {
                $this->listenersInvoker->invoke($class, Events::preUpdate, $entity, new PreUpdateEventArgs($entity, $this->em, $this->getEntityChangeSet($entity)), $preUpdateInvoke);

                $this->recomputeSingleEntityChangeSet($class, $entity);
            }

            if (! empty($this->entityChangeSets[$oid])) {
                $persister->update($entity);
            }

            unset($this->entityUpdates[$oid]);

            if ($postUpdateInvoke !== ListenersInvoker::INVOKE_NONE) {
                $this->listenersInvoker->invoke($class, Events::postUpdate, $entity, new LifecycleEventArgs($entity, $this->em), $postUpdateInvoke);
            }
        }
    }
1274992
public function getNodeInformation(
    $entityClass = '',
        $parentEntity = null
    )
    {
        if ($entityClass === '') {
            throw new Exception('messages.error.classNameNotProvided');
        }
        return $this->repository->getNodeInformation($entityClass, $parentEntity);
    }
614734
private function getMetadata($class)
    {
        $class = ClassUtils::getRealClass(ltrim($class, '\\'));

        if (!array_key_exists($class, $this->metadataCache)) {
            $this->metadataCache[$class] = null;

            if (null !== $manager = $this->registry->getManagerForClass($class)) {
                $this->metadataCache[$class] = $manager->getClassMetadata($class);
            }
        }

        return $this->metadataCache[$class];
    }
351130
protected function getDocumentMetadata($documentClass)
    {
        $factory = new \Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory();
        $factory->setDocumentManager($this->getDocumentManager());
        $factory->setConfiguration($this->getDocumentManager()->getConfiguration());

        $metadata = $factory->getMetadataFor($documentClass);

        return $metadata;
    }
114720
private function fromStdObject(\stdClass $data, $class)
    {
        $reflection   = $this->getReflection($class);
        $object       = $this->getClassInstance($data, $reflection);
        $map          = $this->getPropertyMap($class);
        $this->handleAssociations($data, $object, $reflection, $map['associations'], $map['meta']);
        $this->handleProperties($data, $object, $reflection, $map['fields']);

        return $object;
    }
740726
protected function makeSchema(string $class): array
    {
        //Using as basement
        $schema = $this->schema;
        unset($schema[Record::MORPHED_ALIASES]);

        //We do not have this information in morphed relation but it's required for ManyToMany
        $schema[Record::WHERE] = [];

        //This must be unified in future, for now we can fetch columns directly from there
        $recordSchema = $this->orm->define($class, ORMInterface::R_SCHEMA);
        $schema[Record::RELATION_COLUMNS] = array_keys($recordSchema[Record::SH_DEFAULTS]);

        return $schema;
    }
816798
protected function findMetadata($class)
    {
        $metadata = null;

        try {
            // We could not use the hasMetadataFor() method as it is not working if the entity is not loaded. But
            // the getMetadataFor() method could throw an exception if the class is not found
            $metadata = $this->entityManager->getMetadataFactory()->getMetadataFor($class);
        } catch (Exception $exception) {
            // If an exception is raised, nothing to do. Extra data from metadata will be not used.
        }

        return $metadata;
    }
173239
public function addClass($class)
    {
        if (is_array($class)) {
            $class = implode(' ', $class);
        }

        if (!$this->class) {
            $this->class = [];
        }

        if (is_string($this->class)) {
            throw new Exception(['Property $class should always be array', 'object' => $this, 'class' => $this->class]);
        }

        $this->class = array_merge($this->class, explode(' ', $class));

        return $this;
    }
823170
public function validateClass(ClassMetadata $class)
    {
        $ce = [];

        foreach ($class->getDeclaredPropertiesIterator() as $fieldName => $association) {
            if (! ($association instanceof AssociationMetadata)) {
                continue;
            }

            $ce = array_merge($ce, $this->validateAssociation($class, $association));
        }

        foreach ($class->getSubClasses() as $subClass) {
            if (! in_array($class->getClassName(), class_parents($subClass), true)) {
                $message = "According to the discriminator map class, '%s' has to be a child of '%s', but these entities are not related through inheritance.";

                $ce[] = sprintf($message, $subClass, $class->getClassName());
            }
        }

        return $ce;
    }
570548
public function getRepository($class)
    {
        $classMetadata = $this->getClassMetadataFor($class);
        if (!array_key_exists($class, $this->repositories)) {
            $repositoryClassName = $classMetadata->hasCustomRepository() ? $classMetadata->getRepositoryClass() : BaseRepository::class;
            $this->repositories[$class] = new $repositoryClassName($classMetadata, $this, $class);
        }

        return $this->repositories[$class];
    }
658219
public function parseEntity($class)
    {
        $reflectionClass = new ReflectionClass($class);

        // scan class annotations
        $classAnnotations = $this->reader->getClassAnnotations($reflectionClass);

        // init class metadata
        $entityMetadata = new EntityDefinition([
            'class' => $class,
            'morphClass' => $this->generateMorphClass($class),
            'table' => new TableDefinition([
                'name' => $this->generateTableName($class),
                'columns' => [],
            ]),
            'versionTable' => false,
        
            'softDeletes' => false,
            'timestamps' => false,
            
            'touches' => [],
            'with' => [],

            'columns' => [],
            'attributes' => [],
            'embeddeds' => [],
            'relations' => [],
        ]);

        // find entity parameters and plugins
        foreach ($classAnnotations as $annotation) {
            // entity parameters
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Entity) {
                if (! empty($annotation->morphClass)) {
                    $entityMetadata['morphClass'] = $annotation->morphClass;
                }
                if (! empty($annotation->touches)) {
                    $entityMetadata['touches'] = $annotation->touches;
                }
                if (! empty($annotation->with)) {
                    $entityMetadata['with'] = $annotation->with;
                }
            }

            // softdeletes
            if ($annotation instanceof \ProAI\Datamapper\Annotations\SoftDeletes) {
                $entityMetadata['softDeletes'] = true;
            }

            // table name
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Table) {
                $entityMetadata['table']['name'] = $annotation->name;
            }

            // timestamps
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Timestamps) {
                $entityMetadata['timestamps'] = true;
            }
        }

        // find versionable annotation (2nd loop, because table name is required)
        foreach ($classAnnotations as $annotation) {
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Versionable) {
                $entityMetadata['versionTable'] = new TableDefinition([
                    'name' => $entityMetadata['table']['name'] . '_version',
                    'columns' => [],
                ]);
            }
        }

        // find columns and embedded classes
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            $name = $this->getSanitizedName($reflectionProperty->getName(), $entityMetadata['class']);
            $propertyAnnotations = $this->reader->getPropertyAnnotations($reflectionProperty);

            foreach ($propertyAnnotations as $annotation) {
                // column
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Column) {
                    $this->setAdditionalColumnProperties($name, $annotation, $propertyAnnotations);

                    $this->parseColumn($name, $annotation, $entityMetadata, false, true);
                }

                // embedded class
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Embedded) {
                    $this->parseEmbeddedClass($name, $annotation, $entityMetadata, true);
                }
            }
        }

        // check primary key
        $this->validator->validatePrimaryKey($entityMetadata);

        // find relationships (2nd loop, because primary key column is required for foreign keys)
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            $name = $this->getSanitizedName($reflectionProperty->getName(), $entityMetadata['class']);
            $propertyAnnotations = $this->reader->getPropertyAnnotations($reflectionProperty);

            foreach ($propertyAnnotations as $annotation) {
                // column
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Column) {
                    $this->setAdditionalColumnProperties($name, $annotation, $propertyAnnotations);

                    $entityMetadata['attributes'][] = $this->parseColumn($name, $annotation, $entityMetadata);
                }

                // embedded class
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Embedded) {
                    $entityMetadata['embeddeds'][] = $this->parseEmbeddedClass($name, $annotation, $entityMetadata);
                }

                // relation
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Relation) {
                    $entityMetadata['relations'][] = $this->parseRelation($name, $annotation, $entityMetadata);
                }
            }
        }

        // check timestamps extension
        if (! empty($entityMetadata['timestamps'])) {
            $this->validator->validateTimestamps($entityMetadata);
        }

        // check softDeletes extension
        if (! empty($entityMetadata['softDeletes'])) {
            $this->validator->validateSoftDeletes($entityMetadata);
        }

        // check version extension
        if (! empty($entityMetadata['versionTable'])) {
            $this->validator->validateVersionTable($entityMetadata);
        }

        return $entityMetadata;
    }
240548
private static function initPropertyCache($class) {
        $loops = $class instanceof Object ? $class->getLoops() : Loops::getCurrentLoops();
        $classname = get_class($class);
        $key = "Loops-Misc-AccessTrait-$classname";

        static $cache;

        if(!$cache) {
            $cache = new ChainCache([new ArrayCache, $loops->getService("cache")]);
        }

        if($cache->contains($key)) {
            return $cache->fetch($key);
        }

        $annotations = $loops->getService("annotations");

        // build
        $result["getter"]    = [];
        $result["setter"]    = [];
        $result["exposed"]   = [];
        $result["protected"] = [];
        $result["sleep"]     = [];

        $ro = $annotations->get($classname)->properties->findFirst("Access\ReadOnly");
        $rw = $annotations->get($classname)->properties->findFirst("Access\ReadWrite");

        //make getter
        foreach(array_merge($ro, $rw) as $name => $annotation) {
            if($annotation->getter && !method_exists($class, $annotation->getter)) {
                throw new Exception("Passed getter '{$annotation->getter}' is not a method of class '$classname'.");
            }
            $result["getter"][$name] = $annotation->getter ? [ $annotation->getter, $annotation->arguments ] : $name;
        }

        //make setter
        foreach($rw as $name => $annotation) {
            if($annotation->setter && !method_exists($class, $annotation->setter)) {
                throw new Exception("Passed getter '{$annotation->setter}' is not a method of class '$classname'.");
            }
            $result["setter"][$name] = $annotation->setter ? [ $annotation->setter ] : $name;
        }

        //expose public properties
        foreach((new ReflectionClass($classname))->getProperties() as $property) {
            if($property->isStatic()) {
                continue;
            }

            if($property->isPublic()) {
                $name = $property->getName();
                $result["getter"][$name]  = $name;
                $result["setter"][$name]  = $name;
                $result["exposed"][$name] = $name;
            }

            if($property->isProtected()) {
                $name = $property->getName();
                $result["protected"][$name] = $name;
            }
        }

        //expose properties that have the Exposed annotation - prefer getter of property if exists
        foreach($annotations->get($classname)->properties->findLast("Access\Expose") as $name => $annotation) {
            $result["exposed"][$annotation->name ?: $name] = array_key_exists($name, $result["getter"]) ? $result["getter"][$name] : $name;
        }

        //expose methods that have the Exposed annotation
        foreach($annotations->get($classname)->methods->findLast("Access\Expose") as $name => $annotation) {
            $result["exposed"][$annotation->name ?: $name] = [ $name, $annotation->arguments ];
        }

        //check, which keys must be imported when sleeping
        $current = $classname;
        do {
            $set = $annotations->getStrict($current);

            $properties = array_keys(iterator_to_array($set->properties));

            $properties = array_filter($properties, function($name) use ($current) {
                $property = new ReflectionProperty($current, $name);
                if($property->isStatic()) return FALSE;
                if($property->isPrivate()) return FALSE;
                return TRUE;
            });

            foreach($set->find("Access\Sleep") as $sleep) {
                if($sleep->forbid) {
                    $result["sleep"] = FALSE;
                    break 2;
                }

                if($sleep->include) {
                    $properties = array_intersect($properties, $sleep->include);
                }

                if($sleep->exclude) {
                    $properties = array_diff($properties, $sleep->exclude);
                }
            }

            $result["sleep"] = array_merge($result["sleep"], $properties);
        } while($current = get_parent_class($current));

        $cache->save($key, $result);

        return $result;
    }
935043
private function newInstance(DocumentMetadata $class)
    {
        $document = $class->newInstance();

        // inject ObjectManager upon refresh.
        if ($document instanceof ObjectManagerAware) {
            $document->injectObjectManager($this->manager, $class);
        }

        return $document;
    }
265269
private function getManagerFor($class)
    {
        $manager = $this->doctrine->getManagerForClass($class);

        if ($manager === null) {
            throw new \RuntimeException(
                sprintf(
                    'Class "%s" seems not to be a managed Doctrine entity. Did you forget to map it?',
                    $class
                )
            );
        }

        return $manager;
    }
365566
private function getDoctrineMetadata($entityClass)
    {
        if (!isset($this->doctrineMetadata[$entityClass])) {
            try {
                $this->doctrineMetadata[$entityClass] = $this->em->getClassMetadata($entityClass);
            } catch (MappingException $ex) {
                throw new FiltererException(sprintf('Unable to get Doctrine metadata for class "%s".', $entityClass));
            }
        }

        return $this->doctrineMetadata[$entityClass];
    }