001/*
002 * (C) Copyright 2014 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 *     Nelson Silva <nelson.silva@inevo.pt>
018 */
019package org.nuxeo.ecm.automation.io.services.enricher;
020
021import java.io.IOException;
022import java.util.ArrayList;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.codehaus.jackson.JsonGenerator;
030import org.nuxeo.ecm.core.api.DocumentModel;
031import org.nuxeo.ecm.core.api.model.Property;
032import org.nuxeo.ecm.core.api.model.PropertyNotFoundException;
033import org.nuxeo.ecm.core.schema.SchemaManager;
034import org.nuxeo.ecm.core.schema.types.Field;
035import org.nuxeo.ecm.core.schema.types.Schema;
036import org.nuxeo.ecm.directory.DirectoryException;
037import org.nuxeo.ecm.directory.Session;
038import org.nuxeo.ecm.directory.api.DirectoryService;
039import org.nuxeo.runtime.api.Framework;
040
041/**
042 * This enricher adds the labels for each value of a property referencing dbl10n vocabularies.
043 *
044 * @since 6.0
045 * @deprecated This enricher was migrated to org.nuxeo.ecm.platform.spreadsheet.DCVocabulariesJsonEnricher. The content
046 *             enricher service doesn't work anymore.
047 */
048@Deprecated
049public class VocabularyEnricher extends AbstractContentEnricher {
050
051    protected static final Log log = LogFactory.getLog(VocabularyEnricher.class);
052
053    public static final String DIRECTORY_DEFAULT_LABEL_PREFIX = "label_";
054
055    public static final String KEY_SEPARATOR = "/";
056
057    // Parameters keys
058    public static final String FIELD_PARAMETER = "field";
059
060    public static final String DIRECTORY_PARAMETER = "directoryName";
061
062    // Parameters values
063    private String field;
064
065    private String directoryName;
066
067    private DirectoryService directoryService;
068
069    @Override
070    public void enrich(JsonGenerator jg, RestEvaluationContext ec) throws IOException {
071
072        final DocumentModel doc = ec.getDocumentModel();
073
074        jg.writeStartObject();
075
076        try {
077
078            // Lookup directory schema to find label columns
079            List<String> labelFields = getLabelFields(directoryName);
080
081            // Get the field values
082            String[] entriesIds = getPropertyValues(doc, field);
083
084            // 'field': [
085            jg.writeFieldName(field);
086            jg.writeStartArray();
087
088            // { 'id': ..., 'label_*': ... }
089            if (entriesIds != null) {
090                writeLabels(jg, directoryName, entriesIds, labelFields);
091            }
092
093            // ]
094            jg.writeEndArray();
095
096        } catch (PropertyNotFoundException | DirectoryException e) {
097            log.error(e.getMessage());
098        }
099
100        jg.writeEndObject();
101        jg.flush();
102    }
103
104    @Override
105    public void setParameters(Map<String, String> parameters) {
106        field = parameters.get(FIELD_PARAMETER);
107        if (field == null || field.isEmpty()) {
108            throw new IllegalArgumentException("Parameter '" + FIELD_PARAMETER + "' cannot be empty");
109        }
110        directoryName = parameters.get(DIRECTORY_PARAMETER);
111        if (directoryName == null || directoryName.isEmpty()) {
112            throw new IllegalArgumentException("Parameter '" + DIRECTORY_PARAMETER + "' cannot be empty");
113        }
114    }
115
116    /**
117     * Writes the labels for each entry
118     *
119     * @param jg
120     * @param directoryName
121     * @param entriesIds
122     * @param labelFields
123     * @throws IOException
124     */
125    private void writeLabels(JsonGenerator jg, String directoryName, String[] entriesIds, List<String> labelFields)
126            throws IOException {
127        try (Session session = getDirectoryService().open(directoryName)) {
128            for (String entryId : entriesIds) {
129                Map<String, String> labels = getAbsoluteLabels(entryId, session, labelFields);
130                // Write absolute labels (<parent label> / <child label>)
131                jg.writeStartObject();
132                jg.writeStringField("id", entryId);
133                for (Map.Entry<String, String> label : labels.entrySet()) {
134                    jg.writeStringField(label.getKey(), label.getValue());
135                }
136                jg.writeEndObject();
137            }
138        }
139    }
140
141    /**
142     * Determines label columns based on the label prefix
143     *
144     * @param directoryName the name of the directory to inspect
145     * @return
146     */
147    private List<String> getLabelFields(String directoryName) {
148        String schemaName = getDirectoryService().getDirectorySchema(directoryName);
149
150        SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class);
151
152        Schema schema = schemaManager.getSchema(schemaName);
153
154        List<String> labelFields = new ArrayList<>();
155        String fieldName;
156        for (Field field : schema.getFields()) {
157            fieldName = field.getName().toString();
158            if (fieldName.startsWith(DIRECTORY_DEFAULT_LABEL_PREFIX)) {
159                labelFields.add(fieldName);
160            }
161        }
162
163        return labelFields;
164    }
165
166    private DirectoryService getDirectoryService() {
167        if (directoryService == null) {
168            directoryService = Framework.getLocalService(DirectoryService.class);
169        }
170        return directoryService;
171
172    }
173
174    /**
175     * Return the values of a document's property as an array of strings
176     *
177     * @param doc
178     * @param fieldName
179     * @return
180     */
181    private static String[] getPropertyValues(DocumentModel doc, String fieldName) {
182        String[] entriesIds = null;
183        Property prop = doc.getProperty(fieldName);
184        if (prop.isList()) {
185            entriesIds = prop.getValue(String[].class);
186        } else {
187            String value = prop.getValue(String.class);
188            if (value != null) {
189                entriesIds = new String[] { value };
190            }
191        }
192        return entriesIds;
193    }
194
195    /**
196     * Returns absolute labels for a given entry (<parent label> / <child label>)
197     *
198     * @param entryId
199     * @param session
200     * @param labelFields
201     * @return a map of field: label
202     */
203    private static Map<String, String> getAbsoluteLabels(final String entryId, final Session session,
204            List<String> labelFields) {
205
206        String[] split = entryId.split(KEY_SEPARATOR);
207        Map<String, String> labels = new HashMap<>();
208
209        for (int i = 0; i < split.length; i++) {
210            DocumentModel entry = session.getEntry(split[i]);
211            if (entry == null) {
212                continue;
213            }
214
215            for (String labelField : labelFields) {
216                String result = labels.get(labelField);
217                if (result == null) {
218                    result = "";
219                }
220                String value = (String) entry.getPropertyValue(labelField);
221                result += (i > 0 ? "/" : "") + value;
222                labels.put(labelField, result);
223            }
224
225        }
226
227        return labels;
228    }
229
230}