com.flexive.cmis.spi.SPIUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.cmis.spi.SPIUtils.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.cmis.spi;

import com.flexive.shared.CacheAdmin;
import com.flexive.shared.FxSharedUtils;
import com.flexive.shared.content.FxPK;
import com.flexive.shared.exceptions.FxRuntimeException;
import com.flexive.shared.structure.FxDataType;
import com.flexive.shared.structure.FxProperty;
import com.flexive.shared.structure.FxType;
import com.flexive.shared.tree.FxTreeNode;
import com.flexive.shared.structure.FxPropertyAssignment;
import com.flexive.shared.structure.FxStructureOption;
import com.flexive.shared.value.FxValue;
import org.apache.chemistry.BaseType;
import org.apache.chemistry.ObjectNotFoundException;
import org.apache.chemistry.PropertyType;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Utility methods for the SPI implementation.
 * 
 * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 * @version $Rev$
 */
public class SPIUtils {
    private static final Log LOG = LogFactory.getLog(SPIUtils.class);

    /** Structure option to treat an assignment as a content stream (instead of a binary).
     * The value can be set to the MIME type that will be used for the stream,
     * otherwise it default to text/plain.
     */
    public static final String OPTION_CONTENTSTREAM = "STREAM";

    private SPIUtils() {
    }

    public static boolean isFolderId(String objectId) {
        return StringUtils.isNumeric(objectId);
    }

    public static boolean isDocumentId(String objectId) {
        try {
            Double.parseDouble(objectId); // <id> or <id>.<ver>
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static long getNodeId(String objectId) {
        try {
            return Long.parseLong(objectId);
        } catch (NumberFormatException e) {
            throw new ObjectNotFoundException("Not a valid ID: " + objectId);
        }
    }

    public static FxPK getDocumentId(String objectId) {
        try {
            return FxPK.fromString(objectId);
        } catch (IllegalArgumentException e) {
            throw new ObjectNotFoundException("Not a valid ID: " + objectId);
        }
    }

    public static Calendar convertDate(Object value) {
        if (value instanceof Calendar) {
            return (Calendar) value;
        }
        final Calendar cal = Calendar.getInstance();
        if (value instanceof FxValue) {
            final Object translation = ((FxValue) value).getBestTranslation();
            if (!(translation instanceof Date)) {
                throw new IllegalArgumentException("Value '" + value + "' has type " + value.getClass()
                        + " and cannot be converted to a Date.");
            }
            cal.setTime((Date) translation);
        } else {
            cal.setTime((Date) value);
        }
        return cal;
    }

    public static Set<Long> getFolderTypeIds() {
        return new HashSet<Long>(FxSharedUtils.getSelectableObjectIdList(
                CacheAdmin.getEnvironment().getType(FxType.FOLDER).getDerivedTypes(true, true)));
    }

    public static PropertyType mapPropertyType(FxProperty property) {
        return mapFxDataType(property.getDataType());
    }

    private static PropertyType mapFxDataType(FxDataType dataType) {
        switch (dataType) {
        case String1024:
        case Text:
            return PropertyType.STRING;
        case HTML:
            return PropertyType.STRING;
        // TODO HTML currently not supported by chemistry
        // return PropertyType.HTML;
        case Number:
        case LargeNumber:
            return PropertyType.INTEGER;
        case Float:
        case Double:
            return PropertyType.DECIMAL;
        case Boolean:
            return PropertyType.BOOLEAN;
        case Date:
        case DateTime:
            return PropertyType.DATETIME;
        case Reference:
            return PropertyType.ID;
        case Binary:
            return PropertyType.ID;
        case SelectOne:
        case SelectMany:
        case DateRange:
        case DateTimeRange:
            return PropertyType.STRING; // TODO: ?
        default:
            return PropertyType.STRING; // TODO
        }
    }

    public static Serializable convertValue(FxValue value, FxProperty property) {
        return convertValue(value, mapPropertyType(property));
    }

    public static Serializable convertValue(FxValue value, FlexivePropertyDefinition definition) {
        return convertValue(value.getBestTranslation(), mapPropertyType(definition.getAssignment().getProperty()));
    }

    public static Serializable convertValue(Object value, FxDataType type) {
        return convertValue(value, mapFxDataType(type));
    }

    public static Serializable convertValue(Object value, FxProperty property) {
        return convertValue(value, mapPropertyType(property));
    }

    public static Serializable convertValue(Object value, PropertyType type) {
        if (value == null) {
            return null;
        } else if (type == PropertyType.STRING || type == PropertyType.HTML || type == PropertyType.ID
                || type == PropertyType.URI) {
            return value.toString();
        } else if (type == PropertyType.DATETIME) {
            return convertDate(value);
        } else if (type == PropertyType.INTEGER) {
            return value instanceof Number ? ((Number) value).intValue() : Integer.valueOf(value.toString());
        } else if (type == PropertyType.DECIMAL) {
            return value instanceof Number ? ((Number) value).doubleValue() : Double.valueOf(value.toString());
        } else if (type == PropertyType.BOOLEAN) {
            return value instanceof Boolean ? (Boolean) value : Boolean.valueOf(value.toString());
        } else {
            throw new IllegalArgumentException("No conversion available for value '" + value + "' of class "
                    + value.getClass() + " for property " + type);
        }
    }

    public static boolean typeContainsAssignment(FxType type, String xpath) {
        try {
            type.getPropertyAssignment(xpath);
            return true;
        } catch (FxRuntimeException e) {
            return false;
        }
    }

    /**
     * Map a CMIS type name to the flexive type name.
     *
     * @param typeId    the CMIS type ID
     * @return          the corresponding flexive type
     */
    public static String getFxTypeName(String typeId) {
        if (BaseType.DOCUMENT.toString().equalsIgnoreCase(typeId)) {
            // TODO: this should actually the root type, but the root type isn't really usable here
            return FxType.DOCUMENTFILE;
        } else if (BaseType.FOLDER.toString().equalsIgnoreCase(typeId)) {
            return FxType.FOLDER;
        } else {
            return typeId;
        }
    }

    /**
     * Map a flexive type name to a CMIS type name.
     *
     * @param fxTypeId  the flexive type name
     * @return          the corresponding CMIS type name
     */
    public static String getTypeName(FxType type) {
        if (FxType.FOLDER.equals(type.getName())) {
            return BaseType.FOLDER.getId();
        } else {
            return type.getName();
        }
    }

    /**
     * Return true if the given tree node should be treated as a folder, even
     * though it is (in flexive terms) a document.
     *
     * @param folderTypeIds the folder type IDs (as returned by {@link SPIUtils#getFolderTypeIds()})
     * @param context   the connection context
     * @param child     the tree node to be examined
     * @return          true if the given tree node should be treated as a folder
     */
    static boolean treatDocumentAsFolder(Set<Long> folderTypeIds, FlexiveConnection.Context context,
            FxTreeNode child) {
        return folderTypeIds.contains(child.getReferenceTypeId())
                // check if documents-as-folders connection parameter is set
                || context.getConnectionConfig().isDocumentsAsFolders() && child.getDirectChildCount() > 0;
    }

    /**
     * The property assignment to be used as the content stream.
     *
     * @param type  the content type
     * @return      the property assignment. May be of a different datatype than
     *              FxDataType.Binary to allow the user to flag non-binary
     *              text contents as the "main" content that should be exposed.
     */
    public static FxPropertyAssignment getContentStreamAssignment(FxType type) {
        final FxPropertyAssignment mainBinaryAssignment = type.getMainBinaryAssignment();
        if (mainBinaryAssignment != null) {
            return mainBinaryAssignment;
        }
        // search for a property with the CONTENT_STREAM option set
        for (FxPropertyAssignment property : type.getAllProperties()) {
            if (property.hasOption(OPTION_CONTENTSTREAM)
                    && !FxStructureOption.VALUE_FALSE.equals(property.getOption(OPTION_CONTENTSTREAM).getValue())) {
                if (property.getMultiplicity().getMax() > 1) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn("Assignment " + property.getXPath() + " has CONTENT_STREAM set, "
                                + "but a max. multiplicity > 1 (ignored).");
                    }
                } else {
                    return property;
                }
            }
        }
        return null;
    }

    static void notImplemented(Class cls, String method) {
        System.out.println(cls.getName() + "#" + method + " not implemented yet.");
    }
}