001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Nicolas Chapurlat 018 */ 019package org.nuxeo.ecm.platform.spreadsheet; 020 021import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 022import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 029 030import javax.inject.Inject; 031 032import org.apache.commons.logging.Log; 033import org.apache.commons.logging.LogFactory; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.model.Property; 036import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 037import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher; 038import org.nuxeo.ecm.core.io.registry.reflect.Setup; 039import org.nuxeo.ecm.core.schema.SchemaManager; 040import org.nuxeo.ecm.core.schema.types.Field; 041import org.nuxeo.ecm.core.schema.types.Schema; 042import org.nuxeo.ecm.directory.DirectoryException; 043import org.nuxeo.ecm.directory.Session; 044import org.nuxeo.ecm.directory.api.DirectoryService; 045 046import com.fasterxml.jackson.core.JsonGenerationException; 047import com.fasterxml.jackson.core.JsonGenerator; 048 049@Setup(mode = SINGLETON, priority = REFERENCE) 050public class DCVocabulariesJsonEnricher extends AbstractJsonEnricher<DocumentModel> { 051 052 private static final Log log = LogFactory.getLog(DCVocabulariesJsonEnricher.class); 053 054 public static final String NAME = "vocabularies"; 055 056 private static final String DIRECTORY_DEFAULT_LABEL_PREFIX = "label_"; 057 058 private static final String KEY_SEPARATOR = "/"; 059 060 @Inject 061 private DirectoryService directoryService; 062 063 @Inject 064 private SchemaManager schemaManager; 065 066 public DCVocabulariesJsonEnricher() { 067 super(NAME); 068 } 069 070 @Override 071 public void write(JsonGenerator jg, DocumentModel document) throws IOException { 072 writeVocabulary(jg, document, "l10nsubjects", "dc:subjects"); 073 writeVocabulary(jg, document, "l10ncoverage", "dc:coverage"); 074 } 075 076 private void writeVocabulary(JsonGenerator jg, final DocumentModel doc, String directoryName, String fieldName) 077 throws IOException, JsonGenerationException { 078 try { 079 // Lookup directory schema to find label columns 080 List<String> labelFields = getLabelFields(directoryName); 081 // Get the field values 082 String[] entriesIds = getPropertyValues(doc, fieldName); 083 // 'field': [ 084 jg.writeFieldName(fieldName); 085 jg.writeStartArray(); 086 // { 'id': ..., 'label_*': ... } 087 if (entriesIds != null) { 088 writeLabels(jg, directoryName, entriesIds, labelFields); 089 } 090 // ] 091 jg.writeEndArray(); 092 } catch (PropertyNotFoundException | DirectoryException e) { 093 log.error(e.getMessage()); 094 } 095 } 096 097 /** 098 * Writes the labels for each entry 099 * 100 * @param jg 101 * @param directoryName 102 * @param entriesIds 103 * @param labelFields 104 * @throws IOException 105 */ 106 private void writeLabels(JsonGenerator jg, String directoryName, String[] entriesIds, List<String> labelFields) 107 throws IOException { 108 try (Session session = directoryService.open(directoryName)) { 109 for (String entryId : entriesIds) { 110 Map<String, String> labels = getAbsoluteLabels(entryId, session, labelFields); 111 // Write absolute labels (<parent label> / <child label>) 112 jg.writeStartObject(); 113 jg.writeStringField("id", entryId); 114 for (Map.Entry<String, String> label : labels.entrySet()) { 115 jg.writeStringField(label.getKey(), label.getValue()); 116 } 117 jg.writeEndObject(); 118 } 119 } 120 } 121 122 /** 123 * Determines label columns based on the label prefix 124 * 125 * @param directoryName the name of the directory to inspect 126 * @return 127 */ 128 private List<String> getLabelFields(String directoryName) { 129 String schemaName = directoryService.getDirectorySchema(directoryName); 130 Schema schema = schemaManager.getSchema(schemaName); 131 List<String> labelFields = new ArrayList<String>(); 132 String fieldName; 133 for (Field field : schema.getFields()) { 134 fieldName = field.getName().toString(); 135 if (fieldName.startsWith(DIRECTORY_DEFAULT_LABEL_PREFIX)) { 136 labelFields.add(fieldName); 137 } 138 } 139 return labelFields; 140 } 141 142 /** 143 * Return the values of a document's property as an array of strings 144 * 145 * @param doc 146 * @param fieldName 147 * @return 148 */ 149 private static String[] getPropertyValues(DocumentModel doc, String fieldName) { 150 String[] entriesIds = null; 151 Property prop = doc.getProperty(fieldName); 152 if (prop.isList()) { 153 entriesIds = prop.getValue(String[].class); 154 } else { 155 String value = prop.getValue(String.class); 156 if (value != null) { 157 entriesIds = new String[] { value }; 158 } 159 } 160 return entriesIds; 161 } 162 163 /** 164 * Returns absolute labels for a given entry (<parent label> / <child label>) 165 * 166 * @param entryId 167 * @param session 168 * @param labelFields 169 * @return a map of field: label 170 */ 171 private static Map<String, String> getAbsoluteLabels(final String entryId, final Session session, 172 List<String> labelFields) { 173 String[] split = entryId.split(KEY_SEPARATOR); 174 Map<String, String> labels = new HashMap<>(); 175 for (int i = 0; i < split.length; i++) { 176 DocumentModel entry = session.getEntry(split[i]); 177 if (entry == null) { 178 continue; 179 } 180 for (String labelField : labelFields) { 181 String result = labels.get(labelField); 182 if (result == null) { 183 result = ""; 184 } 185 String value = (String) entry.getPropertyValue(labelField); 186 result += (i > 0 ? "/" : "") + value; 187 labels.put(labelField, result); 188 } 189 } 190 return labels; 191 } 192 193}