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