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