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