001/*
002 * (C) Copyright 2006-2011 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 *     <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
018 *
019 * $Id: DocumentModelUtils.java 28563 2008-01-08 08:56:29Z sfermigier $
020 */
021
022package org.nuxeo.ecm.core.utils;
023
024import java.util.HashMap;
025import java.util.Map;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.PropertyException;
031import org.nuxeo.ecm.core.schema.SchemaManager;
032import org.nuxeo.ecm.core.schema.types.Schema;
033import org.nuxeo.runtime.api.Framework;
034
035/**
036 * Utility methods to deal with property names retrieval.
037 *
038 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
039 */
040public final class DocumentModelUtils {
041
042    private static final Log log = LogFactory.getLog(DocumentModelUtils.class);
043
044    // Utility class.
045    private DocumentModelUtils() {
046    }
047
048    /**
049     * Encodes a property name to use it in a url.
050     *
051     * @param propertyName like dc:title, file:content.3.filename (?)
052     */
053    public static String encodePropertyName(String propertyName) {
054        if (propertyName == null) {
055            return null;
056        }
057        String[] items = propertyName.split(":");
058        return join(items, "/");
059    }
060
061    /**
062     * Decodes a property path given in a url.
063     *
064     * @param propertyPath like dc:title file/content/3/filename (?)
065     */
066    public static String decodePropertyName(String propertyPath) {
067        if (propertyPath == null) {
068            return null;
069        }
070        String[] items = propertyPath.split("/");
071        return join(items, ".");
072    }
073
074    /**
075     * The given propertyName should have 'schema_name:property_name' format.
076     *
077     * @return <code>null</code> if any error occurs.
078     */
079    public static Object getPropertyValue(DocumentModel doc, String propertyName) {
080        try {
081            String schemaName = getSchemaName(propertyName);
082            String fieldName = getFieldName(propertyName);
083            return doc.getProperty(schemaName, fieldName);
084        } catch (PropertyException e) {
085            log.warn("Error trying to get property " + propertyName + ". " + e.getMessage());
086            if (log.isDebugEnabled()) {
087                log.debug(e);
088            }
089            return null;
090        }
091    }
092
093    /**
094     * Obtains a property value given its path.
095     *
096     * @param doc the document
097     * @param propertyPath the property path
098     * @return the property value or <code>null</code> if an error occured.
099     */
100    public static Object getComplexPropertyValue(DocumentModel doc, String propertyPath) {
101        try {
102            return doc.getPropertyValue(propertyPath);
103        } catch (PropertyException e) {
104            return null;
105        }
106    }
107
108    /**
109     * Obtains the schema name from the full propertyName.
110     *
111     * @throws IllegalArgumentException if the propertyName does not have a schema:field pattern
112     */
113    public static String getSchemaName(String propertyName) {
114        String[] s = propertyName.split(":");
115        if (s.length != 2) {
116            throw new IllegalArgumentException("offending value: " + propertyName);
117        }
118        String prefix = s[0];
119        Schema schema = null;
120        SchemaManager tm = Framework.getService(SchemaManager.class);
121        schema = tm.getSchemaFromPrefix(prefix);
122        if (schema == null) {
123            // fall back on prefix as it may be the schema name
124            return prefix;
125        } else {
126            return schema.getName();
127        }
128    }
129
130    /**
131     * Obtains the field name from the full propertyName.
132     *
133     * @throws IllegalArgumentException if the propertyName does not have a schema:field pattern
134     */
135    public static String getFieldName(String propertyName) {
136        int index = propertyName.indexOf(":");
137        if (index == -1) {
138            throw new IllegalArgumentException("offending value: " + propertyName);
139        }
140        return propertyName.substring(index + 1);
141    }
142
143    private static String join(String[] items, String sep) {
144        StringBuilder buf = new StringBuilder();
145        int max = items.length - 1;
146        for (int i = 0; i < items.length; i++) {
147            buf.append(items[i]);
148            if (i < max) {
149                buf.append(sep);
150            }
151        }
152        return buf.toString();
153    }
154
155    /**
156     * Gets all properties defined in declared schemas of a DocumentModel.
157     *
158     * @return map with property names as keys
159     */
160    public static Map<String, Object> getProperties(DocumentModel docModel) {
161        final String[] schemas = docModel.getSchemas();
162        if (schemas == null) {
163            throw new IllegalStateException("schemas are not declared for docModel " + docModel);
164        }
165        final Map<String, Object> allProps = new HashMap<String, Object>();
166        for (String schemaName : schemas) {
167            Map<String, Object> props = docModel.getProperties(schemaName);
168            allProps.putAll(props);
169        }
170        return allProps;
171    }
172
173}