001/* 002 * Copyright 2015 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.contenttype.indexing; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.List; 022 023import org.ametys.cms.contenttype.ContentConstants; 024import org.ametys.cms.contenttype.ContentType; 025import org.ametys.cms.contenttype.MetadataDefinition; 026import org.ametys.cms.contenttype.MetadataDefinitionHolder; 027import org.ametys.cms.contenttype.MetadataType; 028import org.ametys.cms.contenttype.RepeaterDefinition; 029import org.ametys.cms.contenttype.SemanticAnnotation; 030import org.ametys.cms.repository.Content; 031import org.ametys.plugins.repository.metadata.CompositeMetadata; 032import org.ametys.plugins.repository.metadata.RichText; 033import org.ametys.plugins.repository.metadata.UnknownMetadataException; 034import org.ametys.runtime.i18n.I18nizableText; 035 036/** 037 * IndexingField realizing the indexation of semantic annotations. 038 */ 039public class SemanticAnnotationIndexingField implements CustomIndexingField 040{ 041 042 private static final String __ANNOTATION_PREFIX = "annotation-"; 043 044 /** The referenced semantic annotation. */ 045 protected SemanticAnnotation _annotation; 046 047 /** The metadata paths. */ 048 protected List<String> _metaPaths; 049 050 /** The declaring content type. */ 051 protected ContentType _contentType; 052 053 /** 054 * Build a SemanticAnnotationIndexingField. 055 * @param annotation The semantic annotation. 056 * @param metaPaths The paths of the rich text metadatas declaring the annotation. 057 * @param contentType The declaring content type. 058 */ 059 public SemanticAnnotationIndexingField(SemanticAnnotation annotation, Collection<String> metaPaths, ContentType contentType) 060 { 061 _annotation = annotation; 062 _metaPaths = new ArrayList<>(metaPaths); 063 _contentType = contentType; 064 } 065 066 @Override 067 public String getName() 068 { 069 return __ANNOTATION_PREFIX + _annotation.getId(); 070 } 071 072 @Override 073 public I18nizableText getLabel() 074 { 075 return _annotation.getLabel(); 076 } 077 078 @Override 079 public I18nizableText getDescription() 080 { 081 return _annotation.getDescription(); 082 } 083 084 @Override 085 public MetadataType getType() 086 { 087 return MetadataType.STRING; 088 } 089 090 @Override 091 public Object[] getValues(Content content) 092 { 093 List<String> values = new ArrayList<>(); 094 095 for (String metaPath : _metaPaths) 096 { 097 addAnnotationValues(values, content.getMetadataHolder(), _contentType, metaPath); 098 } 099 100 return values.toArray(new String[values.size()]); 101 } 102 103 /** 104 * Add the annotation values from a given rich text to the global value list. 105 * @param values The global value list to fill. 106 * @param metaHolder The current metadata holder. 107 * @param metaDefHolder The current metadata definition holder. 108 * @param metaPath The metadata path from the current metadata holder. 109 */ 110 private void addAnnotationValues(List<String> values, CompositeMetadata metaHolder, MetadataDefinitionHolder metaDefHolder, String metaPath) 111 { 112 try 113 { 114 int slashPos = metaPath.indexOf(ContentConstants.METADATA_PATH_SEPARATOR); 115 116 if (slashPos == -1) 117 { 118 // Last component of the path: get the annotation values from the rich text. 119 addAnnotationValues(values, metaHolder.getRichText(metaPath)); 120 } 121 else 122 { 123 // Intermediary component of the metadata tree. 124 String metaName = metaPath.substring(0, slashPos); 125 String remainingPath = metaPath.substring(slashPos + 1); 126 MetadataDefinition compositeDef = metaDefHolder.getMetadataDefinition(metaName); 127 CompositeMetadata composite = metaHolder.getCompositeMetadata(metaName); 128 129 if (compositeDef instanceof RepeaterDefinition) 130 { 131 // The current metadata is a repeater: get the values from each entry. 132 for (String entryName : composite.getMetadataNames()) 133 { 134 CompositeMetadata entry = composite.getCompositeMetadata(entryName); 135 addAnnotationValues(values, entry, compositeDef, remainingPath); 136 } 137 } 138 else 139 { 140 // The current metadata is a repeater: get the values from each entry. 141 addAnnotationValues(values, composite, compositeDef, remainingPath); 142 } 143 } 144 } 145 catch (UnknownMetadataException e) 146 { 147 // Ignore, just don't add values. 148 } 149 } 150 151 /** 152 * Add the annotation values from a given rich text to the global value list. 153 * @param allValues The global value list to fill. 154 * @param richText The rich text. 155 */ 156 private void addAnnotationValues(List<String> allValues, RichText richText) 157 { 158 if (richText != null) 159 { 160 String[] values = richText.getAnnotationValues(_annotation.getId()); 161 Collections.addAll(allValues, values); 162 } 163 } 164 165}