/**
  * Builds a Mapping collection from the annotation sources that are present
  *
  * @throws \Flowpack\ElasticSearch\Exception
  * @return \Flowpack\ElasticSearch\Mapping\MappingCollection<\Flowpack\ElasticSearch\Domain\Model\Mapping>
  */
 public function buildMappingInformation()
 {
     if (!$this->client instanceof Model\Client) {
         throw new \Flowpack\ElasticSearch\Exception('No client was given for mapping retrieval. Set a client BackendMappingBuilder->setClient().', 1339678111);
     }
     $this->indicesWithoutTypeInformation = array();
     $response = $this->client->request('GET', '/_mapping');
     $mappingInformation = new MappingCollection(MappingCollection::TYPE_BACKEND);
     $mappingInformation->setClient($this->client);
     $indexNames = $this->indexInformer->getAllIndexNames();
     foreach ($response->getTreatedContent() as $indexName => $indexSettings) {
         if (!in_array($indexName, $indexNames)) {
             continue;
         }
         $index = new Model\Index($indexName);
         if (empty($indexSettings)) {
             $this->indicesWithoutTypeInformation[] = $indexName;
         }
         foreach ($indexSettings as $typeName => $typeSettings) {
             $type = new Model\GenericType($index, $typeName);
             $mapping = new Model\Mapping($type);
             if (isset($typeSettings['properties'])) {
                 foreach ($typeSettings['properties'] as $propertyName => $propertySettings) {
                     foreach ($propertySettings as $key => $value) {
                         $mapping->setPropertyByPath(array($propertyName, $key), $value);
                     }
                 }
             }
             $mappingInformation->add($mapping);
         }
     }
     return $mappingInformation;
 }
 /**
  * Tells whether a member of this collection has a specific index/type/property settings value
  *
  * @param \Flowpack\ElasticSearch\Domain\Model\Mapping $inquirerMapping
  * @param string $propertyName
  * @param $settingKey
  *
  * @return mixed
  */
 public function getMappingSetting(\Flowpack\ElasticSearch\Domain\Model\Mapping $inquirerMapping, $propertyName, $settingKey)
 {
     foreach ($this as $memberMapping) {
         /** @var $memberMapping \Flowpack\ElasticSearch\Domain\Model\Mapping */
         if ($inquirerMapping->getType()->getName() === $memberMapping->getType()->getName() && $inquirerMapping->getType()->getIndex()->getName() === $memberMapping->getType()->getIndex()->getName()) {
             return $memberMapping->getPropertyByPath(array($propertyName, $settingKey));
         }
     }
     return NULL;
 }
 /**
  * Builds a Mapping Collection from the configured node types
  *
  * @param \Flowpack\ElasticSearch\Domain\Model\Index $index
  * @return \Flowpack\ElasticSearch\Mapping\MappingCollection<\Flowpack\ElasticSearch\Domain\Model\Mapping>
  */
 public function buildMappingInformation(Index $index)
 {
     $this->lastMappingErrors = new \TYPO3\Flow\Error\Result();
     $mappings = new MappingCollection(MappingCollection::TYPE_ENTITY);
     /** @var NodeType $nodeType */
     foreach ($this->nodeTypeManager->getNodeTypes() as $nodeTypeName => $nodeType) {
         if ($nodeTypeName === 'unstructured' || $nodeType->isAbstract()) {
             continue;
         }
         $type = $index->findType(self::convertNodeTypeNameToMappingName($nodeTypeName));
         $mapping = new Mapping($type);
         // http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-root-object-type.html#_dynamic_templates
         // 'not_analyzed' is necessary
         $mapping->addDynamicTemplate('dimensions', array('path_match' => '__dimensionCombinations.*', 'match_mapping_type' => 'string', 'mapping' => array('type' => 'string', 'index' => 'not_analyzed')));
         foreach ($nodeType->getProperties() as $propertyName => $propertyConfiguration) {
             if (isset($propertyConfiguration['search']) && isset($propertyConfiguration['search']['elasticSearchMapping'])) {
                 if (is_array($propertyConfiguration['search']['elasticSearchMapping'])) {
                     $mapping->setPropertyByPath($propertyName, $propertyConfiguration['search']['elasticSearchMapping']);
                 }
             } elseif (isset($propertyConfiguration['type']) && isset($this->defaultConfigurationPerType[$propertyConfiguration['type']]['elasticSearchMapping'])) {
                 if (is_array($this->defaultConfigurationPerType[$propertyConfiguration['type']]['elasticSearchMapping'])) {
                     $mapping->setPropertyByPath($propertyName, $this->defaultConfigurationPerType[$propertyConfiguration['type']]['elasticSearchMapping']);
                 }
             } else {
                 $this->lastMappingErrors->addWarning(new \TYPO3\Flow\Error\Warning('Node Type "' . $nodeTypeName . '" - property "' . $propertyName . '": No ElasticSearch Mapping found.'));
             }
         }
         $mappings->add($mapping);
     }
     return $mappings;
 }
 /**
  * @param Mapping $mapping
  * @param string $className
  * @param string $propertyName
  *
  * @throws \Flowpack\ElasticSearch\Exception
  * @return void
  */
 protected function augmentMappingByProperty(Mapping $mapping, $className, $propertyName)
 {
     list($propertyType) = $this->reflectionService->getPropertyTagValues($className, $propertyName, 'var');
     if (($transformAnnotation = $this->reflectionService->getPropertyAnnotation($className, $propertyName, 'Flowpack\\ElasticSearch\\Annotations\\Transform')) !== NULL) {
         $mappingType = $this->transformerFactory->create($transformAnnotation->type)->getTargetMappingType();
     } elseif (\TYPO3\Flow\Utility\TypeHandling::isSimpleType($propertyType)) {
         $mappingType = $propertyType;
     } elseif ($propertyType === '\\DateTime') {
         $mappingType = 'date';
     } else {
         throw new \Flowpack\ElasticSearch\Exception('Mapping is only supported for simple types and DateTime objects; "' . $propertyType . '" given but without a Transform directive.');
     }
     $mapping->setPropertyByPath($propertyName, array('type' => $mappingType));
     $annotation = $this->reflectionService->getPropertyAnnotation($className, $propertyName, 'Flowpack\\ElasticSearch\\Annotations\\Mapping');
     if ($annotation instanceof MappingAnnotation) {
         $mapping->setPropertyByPath($propertyName, $this->processMappingAnnotation($annotation, $mapping->getPropertyByPath($propertyName)));
         if ($annotation->getFields()) {
             foreach ($annotation->getFields() as $multiFieldAnnotation) {
                 $multiFieldIndexName = trim($multiFieldAnnotation->index_name);
                 if ($multiFieldIndexName === '') {
                     throw new \Flowpack\ElasticSearch\Exception('Multi field require an unique index name "' . $className . '::' . $propertyName . '".');
                 }
                 if (isset($multiFields[$multiFieldIndexName])) {
                     throw new \Flowpack\ElasticSearch\Exception('Duplicate index name in the same multi field is not allowed "' . $className . '::' . $propertyName . '".');
                 }
                 $multiFieldAnnotation->type = $mappingType;
                 $multiFields[$multiFieldIndexName] = $this->processMappingAnnotation($multiFieldAnnotation);
             }
             $mapping->setPropertyByPath(array($propertyName, 'fields'), $multiFields);
         }
     }
 }