/*
* Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.registry.cmis;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.Cardinality;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.impl.Converter;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.*;
import org.apache.chemistry.opencmis.server.support.TypeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.registry.cmis.impl.UnversionedDocumentTypeHandler;
import org.wso2.carbon.registry.cmis.util.CMISConstants;
import java.math.BigInteger;
import java.util.*;
/**
* This class corresponds to different CMIS types and handles the related mappings.
*/
public class RegistryTypeManager implements TypeManager {
private static final Logger log = LoggerFactory.getLogger(RegistryTypeManager.class);
public static final String DOCUMENT_TYPE_ID = "cmis:document";
public static final String FOLDER_TYPE_ID = "cmis:folder";
public static final String RELATIONSHIP_TYPE_ID = "cmis:relationship";
public static final String POLICY_TYPE_ID = "cmis:policy";
public static final String NAMESPACE = "http://wso2.org/greg";
private final Map<String, TypeDefinitionContainerImpl> fTypes;
public RegistryTypeManager() {
fTypes = new HashMap<String, TypeDefinitionContainerImpl>();
}
/**
* Adds a type to collection with inheriting base type properties.
* @param type type to add
* @return <code>true</code> iff the type was successfully added
*/
public boolean addType(TypeDefinition type) {
if (type == null) {
return false;
}
if (fTypes.containsKey(type.getId())) {
// can't overwrite a type
return false;
}
AbstractTypeDefinition newType = (AbstractTypeDefinition) copyTypeDefinition(type);
if (!newType.getBaseTypeId().value().equals(newType.getId())) {
// find base type
TypeDefinition baseType;
if (newType.getBaseTypeId() == BaseTypeId.CMIS_DOCUMENT) {
baseType = copyTypeDefinition(fTypes.get(DOCUMENT_TYPE_ID).getTypeDefinition());
}
else if (newType.getBaseTypeId() == BaseTypeId.CMIS_FOLDER) {
baseType = copyTypeDefinition(fTypes.get(FOLDER_TYPE_ID).getTypeDefinition());
}
else if (newType.getBaseTypeId() == BaseTypeId.CMIS_RELATIONSHIP) {
baseType = copyTypeDefinition(fTypes.get(RELATIONSHIP_TYPE_ID).getTypeDefinition());
}
else if (newType.getBaseTypeId() == BaseTypeId.CMIS_POLICY) {
baseType = copyTypeDefinition(fTypes.get(POLICY_TYPE_ID).getTypeDefinition());
}
else {
return false;
}
// copy property definition
for (PropertyDefinition<?> propDef : baseType.getPropertyDefinitions().values()) {
((AbstractPropertyDefinition<?>) propDef).setIsInherited(true);
newType.addPropertyDefinition(propDef);
}
}
// add it
addTypeInternal(newType);
log.info("Added type '" + newType.getId() + "'.");
return true;
}
public TypeDefinition getType(String typeId) {
TypeDefinitionContainer tc = fTypes.get(typeId);
return tc == null ? null : tc.getTypeDefinition();
}
public static boolean isVersionable(TypeDefinition typeDef) {
return (!typeDef.getId().equals(UnversionedDocumentTypeHandler.DOCUMENT_UNVERSIONED_TYPE_ID));
}
public static TypeDefinition copyTypeDefinition(TypeDefinition type) {
return Converter.convert(Converter.convert(type));
}
/**
* See CMIS 1.0 section 2.2.2.3 getTypeChildren
*/
public TypeDefinitionList getTypeChildren(String typeId, boolean includePropertyDefinitions,
BigInteger maxItems, BigInteger skipCount) {
TypeDefinitionListImpl result = new TypeDefinitionListImpl(new ArrayList<TypeDefinition>());
int skip = skipCount == null ? 0 : skipCount.intValue();
if (skip < 0) {
skip = 0;
}
int max = maxItems == null ? Integer.MAX_VALUE : maxItems.intValue();
if (max < 1) {
return result;
}
if (typeId == null) {
if (skip < 1) {
result.getList().add(copyTypeDefinition(fTypes.get(FOLDER_TYPE_ID).getTypeDefinition()));
max--;
}
if (skip < 2 && max > 0) {
result.getList().add(copyTypeDefinition(fTypes.get(DOCUMENT_TYPE_ID).getTypeDefinition()));
}
result.setHasMoreItems(result.getList().size() + skip < 2);
result.setNumItems(BigInteger.valueOf(2));
} else {
TypeDefinitionContainer tc = fTypes.get(typeId);
if (tc == null || tc.getChildren() == null) {
return result;
}
for (TypeDefinitionContainer child : tc.getChildren()) {
if (skip > 0) {
skip--;
continue;
}
result.getList().add(copyTypeDefinition(child.getTypeDefinition()));
max--;
if (max == 0) {
break;
}
}
result.setHasMoreItems(result.getList().size() + skip < tc.getChildren().size());
result.setNumItems(BigInteger.valueOf(tc.getChildren().size()));
}
if (!includePropertyDefinitions) {
for (TypeDefinition type : result.getList()) {
type.getPropertyDefinitions().clear();
}
}
return result;
}
/**
* See CMIS 1.0 section 2.2.2.4 getTypeDescendants
*/
public List<TypeDefinitionContainer> getTypesDescendants(String typeId, BigInteger depth,
Boolean includePropertyDefinitions) {
List<TypeDefinitionContainer> result = new ArrayList<TypeDefinitionContainer>();
// check depth
int d = depth == null ? -1 : depth.intValue();
if (d == 0) {
throw new CmisInvalidArgumentException("Depth must not be 0!");
}
// set property definition flag to default value if not set
boolean ipd = Boolean.TRUE.equals(includePropertyDefinitions);
if (typeId == null) {
result.add(getTypesDescendants(d, fTypes.get(FOLDER_TYPE_ID), ipd));
result.add(getTypesDescendants(d, fTypes.get(DOCUMENT_TYPE_ID), ipd));
} else {
TypeDefinitionContainer tc = fTypes.get(typeId);
if (tc != null) {
result.add(getTypesDescendants(d, tc, ipd));
}
}
return result;
}
//GregTypeManager
public TypeDefinitionContainer getTypeById(String typeId) {
return fTypes.get(typeId);
}
public TypeDefinition getTypeByQueryName(String typeQueryName) {
for (TypeDefinitionContainerImpl type : fTypes.values()) {
TypeDefinition typeDef = type.getTypeDefinition();
if (typeDef.getQueryName().equals(typeQueryName)) {
return typeDef;
}
}
return null;
}
public Collection<TypeDefinitionContainer> getTypeDefinitionList() {
Collection<TypeDefinitionContainer> types = new ArrayList<TypeDefinitionContainer>(fTypes.size());
types.addAll(fTypes.values());
return types;
}
public List<TypeDefinitionContainer> getRootTypes() {
List<TypeDefinitionContainer> types = new ArrayList<TypeDefinitionContainer>(2);
types.add(fTypes.get(FOLDER_TYPE_ID));
types.add(fTypes.get(DOCUMENT_TYPE_ID));
return types;
}
public String getPropertyIdForQueryName(TypeDefinition typeDefinition, String propQueryName) {
for (PropertyDefinition<?> pd : typeDefinition.getPropertyDefinitions().values()) {
if (pd.getQueryName().equals(propQueryName)) {
return pd.getId();
}
}
return null;
}
public static void addBasePropertyDefinitions(AbstractTypeDefinition type) {
type.addPropertyDefinition(createPropDef(PropertyIds.BASE_TYPE_ID, CMISConstants.BASE_TYPE_ID_VALUE, CMISConstants.BASE_TYPE_ID_VALUE,
PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.OBJECT_ID, CMISConstants.OBJECT_ID_VALUE, CMISConstants.OBJECT_ID_VALUE, PropertyType.ID,
Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.OBJECT_TYPE_ID, CMISConstants.TYPE_ID_VALUE, CMISConstants.TYPE_ID_VALUE, PropertyType.ID,
Cardinality.SINGLE, Updatability.ONCREATE, false, true));
type.addPropertyDefinition(createPropDef(PropertyIds.NAME, CMISConstants.NAME_VALUE, CMISConstants.NAME_VALUE, PropertyType.STRING,
Cardinality.SINGLE, Updatability.READWRITE, false, true));
type.addPropertyDefinition(createPropDef(PropertyIds.CREATED_BY, CMISConstants.CREATED_BY_VALUE, CMISConstants.CREATED_BY_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CREATION_DATE, CMISConstants.CREATION_DATE_VALUE, CMISConstants.CREATION_DATE_VALUE,
PropertyType.DATETIME, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.LAST_MODIFIED_BY, CMISConstants.LAST_MODIFIED_BY_VALUE, CMISConstants.LAST_MODIFIED_BY_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.LAST_MODIFICATION_DATE, CMISConstants.LAST_MODIFIED_DATE_VALUE,
CMISConstants.LAST_MODIFIED_DATE_VALUE, PropertyType.DATETIME, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CHANGE_TOKEN, CMISConstants.CHANGE_TOKEN_VALUE, CMISConstants.CHANGE_TOKEN_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
}
public static void addFolderPropertyDefinitions(FolderTypeDefinitionImpl type) {
type.addPropertyDefinition(createPropDef(PropertyIds.PARENT_ID, CMISConstants.PARENT_ID_VALUE, CMISConstants.PARENT_ID_VALUE, PropertyType.ID,
Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS,
CMISConstants.ALLOWED_CHILD_TYPE_VALUE, CMISConstants.ALLOWED_CHILD_TYPE_VALUE, PropertyType.ID, Cardinality.MULTI,
Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.PATH, CMISConstants.PATH_VALUE, CMISConstants.PATH_VALUE, PropertyType.STRING,
Cardinality.SINGLE, Updatability.READONLY, false, false));
}
public static void addDocumentPropertyDefinitions(DocumentTypeDefinitionImpl type) {
type.addPropertyDefinition(createPropDef(PropertyIds.IS_IMMUTABLE, CMISConstants.IS_IMMUTABLE_VALUE, CMISConstants.IS_IMMUTABLE_VALUE,
PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.IS_LATEST_VERSION, CMISConstants.IS_LATEST_VERSION_VALUE,
CMISConstants.IS_LATEST_VERSION_VALUE, PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.IS_MAJOR_VERSION, CMISConstants.IS_MAJOR_VERSION_VALUE, CMISConstants.IS_MAJOR_VERSION_VALUE,
PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.IS_LATEST_MAJOR_VERSION, CMISConstants.IS_LATEST_MAJOR_VERSION_VALUE,
CMISConstants.IS_LATEST_MAJOR_VERSION_VALUE, PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false,
false));
type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_LABEL, CMISConstants.VERSION_LABEL_VALUE, CMISConstants.VERSION_LABEL_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_SERIES_ID, CMISConstants.VERSION_SERIES_ID_VALUE,
CMISConstants.VERSION_SERIES_ID_VALUE, PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT,
CMISConstants.IS_VERSION_CHECKED_OUT_VALUE, CMISConstants.IS_VERSION_CHECKED_OUT_VALUE, PropertyType.BOOLEAN,
Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID,
CMISConstants.VERSION_CHECKED_OUT_ID_VALUE, CMISConstants.VERSION_CHECKED_OUT_ID_VALUE, PropertyType.ID, Cardinality.SINGLE,
Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY,
CMISConstants.VERSION_CHECKED_OUT_BY_VALUE, CMISConstants.VERSION_CHECKED_OUT_BY_VALUE, PropertyType.STRING, Cardinality.SINGLE,
Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CHECKIN_COMMENT, CMISConstants.CHECKIN_COMMENT_VALUE, CMISConstants.CHECKIN_COMMENT_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_LENGTH, CMISConstants.CONTENT_STREAM_LENGTH_VALUE,
CMISConstants.CONTENT_STREAM_LENGTH_VALUE, PropertyType.INTEGER, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_MIME_TYPE, CMISConstants.MIME_TYPE_VALUE, CMISConstants.MIME_TYPE_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_FILE_NAME, CMISConstants.FILE_NAME_VALUE, CMISConstants.FILE_NAME_VALUE,
PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false));
type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_ID, CMISConstants.CONTENT_STREAM_ID_VALUE,
CMISConstants.CONTENT_STREAM_ID_VALUE, PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false));
}
/**
* Creates a property definition object.
*/
public static PropertyDefinition<?> createPropDef(String id, String displayName, String description,
PropertyType datatype, Cardinality cardinality, Updatability updateability, boolean inherited,
boolean required) {
AbstractPropertyDefinition<?> result;
switch (datatype) {
case BOOLEAN:
result = new PropertyBooleanDefinitionImpl();
break;
case DATETIME:
result = new PropertyDateTimeDefinitionImpl();
break;
case DECIMAL:
result = new PropertyDecimalDefinitionImpl();
break;
case HTML:
result = new PropertyHtmlDefinitionImpl();
break;
case ID:
result = new PropertyIdDefinitionImpl();
break;
case INTEGER:
result = new PropertyIntegerDefinitionImpl();
break;
case STRING:
result = new PropertyStringDefinitionImpl();
break;
case URI:
result = new PropertyUriDefinitionImpl();
break;
default:
throw new RuntimeException("Unknown datatype! Spec change?");
}
result.setId(id);
result.setLocalName(id);
result.setDisplayName(displayName);
result.setDescription(description);
result.setPropertyType(datatype);
result.setCardinality(cardinality);
result.setUpdatability(updateability);
result.setIsInherited(inherited);
result.setIsRequired(required);
result.setIsQueryable(true);
result.setQueryName(id);
result.setIsOrderable(true);
return result;
}
/**
* Adds a type to collection.
*/
private void addTypeInternal(AbstractTypeDefinition type) {
if (type == null) {
return;
}
TypeDefinitionContainerImpl tc = new TypeDefinitionContainerImpl();
tc.setTypeDefinition(type);
// add to parent
if (type.getParentTypeId() != null) {
TypeDefinitionContainerImpl tdc = fTypes.get(type.getParentTypeId());
if (tdc != null) {
if (tdc.getChildren() == null) {
tdc.setChildren(new ArrayList<TypeDefinitionContainer>());
}
tdc.getChildren().add(tc);
}
}
fTypes.put(type.getId(), tc);
}
/**
* Gathers the type descendants tree.
*/
private static TypeDefinitionContainer getTypesDescendants(int depth, TypeDefinitionContainer tc,
boolean includePropertyDefinitions) {
TypeDefinitionContainerImpl result = new TypeDefinitionContainerImpl();
TypeDefinition type = copyTypeDefinition(tc.getTypeDefinition());
if (!includePropertyDefinitions) {
type.getPropertyDefinitions().clear();
}
result.setTypeDefinition(type);
if (depth != 0) {
if (tc.getChildren() != null) {
result.setChildren(new ArrayList<TypeDefinitionContainer>());
for (TypeDefinitionContainer tdc : tc.getChildren()) {
result.getChildren().add(
getTypesDescendants(depth < 0 ? -1 : depth - 1, tdc, includePropertyDefinitions));
}
}
}
return result;
}
}