diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml index a5eab11b75..954291fef2 100644 --- a/config/alfresco/application-context.xml +++ b/config/alfresco/application-context.xml @@ -46,6 +46,7 @@ + diff --git a/config/alfresco/cmis-api-context.xml b/config/alfresco/cmis-api-context.xml new file mode 100644 index 0000000000..7ead43bf1e --- /dev/null +++ b/config/alfresco/cmis-api-context.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + true + + + + + + + + + + alfresco/model/cmisModel.xml + + + + + \ No newline at end of file diff --git a/config/alfresco/model/cmisModel.xml b/config/alfresco/model/cmisModel.xml new file mode 100644 index 0000000000..e27ddc83ae --- /dev/null +++ b/config/alfresco/model/cmisModel.xml @@ -0,0 +1,348 @@ + + + CMIS Model Definitions + 1.0 + + + + + + + + + + + + + + + Document + Document Type + + + Is Immutable + Is the document immutable? + d:boolean + true + false + false + + + + Is Latest Version + Is this the latest version of the document? + d:boolean + true + true + false + + true + + + + Is Major Version + Is this a major version of the document? + d:boolean + true + false + false + + true + + + + Is Latest Major Version + Is this the latest major version of the document? + d:boolean + true + false + false + + true + + + + Version Series Is Checked Out + Is the version series checked out? + d:boolean + true + true + false + + true + + + + Version Series Checked Out By + The authority who checked out this document version series + d:text + true + false + false + + true + + + + Version Series Checked Out Id + The checked out version series id + d:noderef + true + false + false + + true + + + + Checkin Comment + The checkin comment + d:text + true + false + false + + true + + + + Content Stream Allowed + Is a content stream allowed? + d:boolean + true + true + false + + true + + + + Content Stream Length + The length of the content stream + d:int + true + false + false + + true + + + + Content Stream MIME Type + The content stream MIME type + d:text + true + false + false + + true + + + + Content Stream Filename + The content stream filename + d:text + false + false + false + + true + + + + Content Stream URI + The content stream URI + d:text + true + false + false + + true + + + + + cmis:NAMED + + + + + + Folder + Folder Type + + + Parent + The parent of the folder + d:noderef + true + true + false + + false + + + + Allowed Child Object Types + The allowed child object types + d:qname + true + false + true + + false + + + + + cmis:NAMED + + + + + Relationship + Relationship Type + + + Source Id + The source id for the relationship + d:noderef + true + true + false + + false + + + + Target Id + The target id for the relationship + d:noderef + true + true + false + + false + + + + + cmis:CORE + + + + + + + + + + Object Id + The unique object id (a node ref) + d:noderef + true + true + false + + false + + + + URI + URI + d:text + true + false + false + + false + + + + Object Type Id + The object type id + d:qname + true + true + false + + false + + + + Created by + The authority who created this object + d:text + true + true + false + + false + + + + Creation Date + The object creation date + d:datetime + true + true + false + + false + + + + Last Modified By + The authority who last modified this object + d:text + true + true + false + + false + + + + Last Modified Date + The date this object was last modified + d:datetime + true + true + false + + false + + + + Change token + Change Token + d:text + true + true + false + + false + + + + + + + cmis:CORE + + + Name + Name + d:text + false + true + false + + both + + + + + + + \ No newline at end of file diff --git a/source/java/org/alfresco/cmis/dictionary/BaseCMISTest.java b/source/java/org/alfresco/cmis/dictionary/BaseCMISTest.java new file mode 100644 index 0000000000..f35afecc16 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/BaseCMISTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +import javax.transaction.Status; +import javax.transaction.UserTransaction; + +import junit.framework.TestCase; + +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.ApplicationContextHelper; +import org.springframework.context.ApplicationContext; + +/** + * Base CMIS test + * Basic TX control and authentication + * + * @author andyh + * + */ +public abstract class BaseCMISTest extends TestCase +{ + private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); + + protected CMISDictionaryService cmisDictionaryService; + + protected DictionaryService dictionaryService; + + protected TransactionService transactionService; + + protected AuthenticationComponent authenticationComponent; + + protected UserTransaction testTX; + + public void setUp() throws Exception + { + cmisDictionaryService = (CMISDictionaryService) ctx.getBean("CMISDictionaryService"); + dictionaryService = (DictionaryService) ctx.getBean("dictionaryService"); + + transactionService = (TransactionService) ctx.getBean("transactionComponent"); + authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent"); + + testTX = transactionService.getUserTransaction(); + testTX.begin(); + this.authenticationComponent.setSystemUserAsCurrentUser(); + + + } + + @Override + protected void tearDown() throws Exception + { + + if (testTX.getStatus() == Status.STATUS_ACTIVE) + { + testTX.rollback(); + } + AuthenticationUtil.clearCurrentSecurityContext(); + super.tearDown(); + } +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISCardinality.java b/source/java/org/alfresco/cmis/dictionary/CMISCardinality.java new file mode 100644 index 0000000000..fc186eae48 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISCardinality.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +/** + * Cardinality for property definitions + * + * @author andyh + * + */ +public enum CMISCardinality +{ + /** + * Single-valued + */ + SINGLE_VALUED, + /** + * Multi-valued + */ + MULTI_VALUED; +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISChoice.java b/source/java/org/alfresco/cmis/dictionary/CMISChoice.java new file mode 100644 index 0000000000..1f4489498d --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISChoice.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +import java.util.Collection; + +/** + * Choice for property definitions + * + * @author andyh + * + */ +public class CMISChoice +{ + /** + * Get the name of the choice + * @return + */ + public String getName() + { + throw new UnsupportedOperationException(); + } + + /** + * Get the value when chosen + * @return + */ + public CMISPropertyValue getValue() + { + throw new UnsupportedOperationException(); + } + + /** + * Get the index that determined the choices position amongst it siblings + * @return + */ + public int getIndex() + { + throw new UnsupportedOperationException(); + } + + /** + * Get sub-choices + * @return + */ + public Collection getChildren() + { + throw new UnsupportedOperationException(); + } +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISDictionaryService.java b/source/java/org/alfresco/cmis/dictionary/CMISDictionaryService.java new file mode 100644 index 0000000000..f858bb9a3f --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISDictionaryService.java @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * Service to query the CMIS meta model + * + * @author andyh + */ +public class CMISDictionaryService +{ + + private DictionaryService dictionaryService; + + private NamespaceService namespaceService; + + private boolean strict = true; + + /** + * Set the dictionary Service + * + * @param dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * Set the namespace service + * + * @param namespaceService + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * Is the service strict (CMIS types only) + * + * @return + */ + public boolean isStrict() + { + return strict; + } + + /** + * Set strict mode. In strict mode only CMIS types and properties are returned + * + * @param strict + */ + public void setStrict(boolean strict) + { + this.strict = strict; + } + + /** + * Get the all the object types ids TODO: Note there can be name collisions between types and associations. e.g. + * app:configurations + * + * @return + */ + public Collection getAllObjectTypeIds() + { + Collection alfrescoTypeQNames; + Collection alfrescoAssociationQNames; + + if (strict) + { + alfrescoTypeQNames = dictionaryService.getTypes(CMISMapping.CMIS_MODEL_QNAME); + alfrescoAssociationQNames = dictionaryService.getAssociations(CMISMapping.CMIS_MODEL_QNAME); + } + else + { + alfrescoTypeQNames = dictionaryService.getAllTypes(); + alfrescoAssociationQNames = dictionaryService.getAllAssociations(); + } + + Collection answer = new HashSet(alfrescoTypeQNames.size() + alfrescoAssociationQNames.size()); + + for (QName typeQName : alfrescoTypeQNames) + { + if (CMISMapping.isValidCmisType(dictionaryService, typeQName)) + { + answer.add(CMISMapping.getCmisTypeId(typeQName)); + } + } + + for (QName associationName : alfrescoAssociationQNames) + { + if (CMISMapping.isValidCmisAssociation(dictionaryService, associationName)) + { + answer.add(CMISMapping.getCmisTypeId(associationName)); + } + } + + return answer; + } + + /** + * Get the object type definition TODO: Note there can be name collisions between types and associations. e.g. + * app:configurations Currently clashing types will give inconsistent behaviour + * + * @param typeId + * @return + */ + public CMISTypeDefinition getType(CMISTypeId typeId) + { + // Types + QName typeQName = CMISMapping.getTypeQname(typeId); + TypeDefinition typeDefinition = dictionaryService.getType(typeQName); + if (typeDefinition != null) + { + if (CMISMapping.isValidCmisType(dictionaryService, typeQName)) + { + return new CMISTypeDefinition(dictionaryService, namespaceService, typeQName); + } + else + { + return null; + } + } + + // Associations + AssociationDefinition associationDefinition = dictionaryService.getAssociation(typeQName); + if (associationDefinition != null) + { + if (CMISMapping.isValidCmisAssociation(dictionaryService, typeQName)) + { + return new CMISTypeDefinition(dictionaryService, namespaceService, typeQName); + } + else + { + return null; + } + } + + // Unknown type + return null; + } + + /** + * Get all the property definitions for a type + * + * @param typeId + * @return + */ + public Map getPropertyDefinitions(CMISTypeId typeId) + { + HashMap properties = new HashMap(); + + QName typeQName = CMISMapping.getTypeQname(typeId); + TypeDefinition typeDefinition = dictionaryService.getType(typeQName); + if (typeDefinition != null) + { + if (CMISMapping.isValidCmisType(dictionaryService, typeQName)) + { + for (QName qname : typeDefinition.getProperties().keySet()) + { + if (CMISMapping.getPropertyType(dictionaryService, qname) != null) + { + CMISPropertyDefinition cmisPropDefinition = new CMISPropertyDefinition(dictionaryService, namespaceService, qname); + properties.put(cmisPropDefinition.getPropertyName(), cmisPropDefinition); + } + } + for (AspectDefinition aspect : typeDefinition.getDefaultAspects()) + { + for (QName qname : aspect.getProperties().keySet()) + { + if (CMISMapping.getPropertyType(dictionaryService, qname) != null) + { + CMISPropertyDefinition cmisPropDefinition = new CMISPropertyDefinition(dictionaryService, namespaceService, qname); + properties.put(cmisPropDefinition.getPropertyName(), cmisPropDefinition); + } + } + } + } + else + { + return properties; + } + } + + // Associations + AssociationDefinition associationDefinition = dictionaryService.getAssociation(typeQName); + if (associationDefinition != null) + { + if (CMISMapping.isValidCmisAssociation(dictionaryService, typeQName)) + { + return getPropertyDefinitions(new CMISTypeId(CMISMapping.RELATIONSHIP_OBJECT_TYPE)); + } + else + { + return properties; + } + } + + // Unknown type + return properties; + } + + /** + * Get a single property definition + * + * @param typeId + * @param propertyName + * @return + */ + public CMISPropertyDefinition getPropertyDefinition(CMISTypeId typeId, String propertyName) + { + return getPropertyDefinitions(typeId).get(propertyName); + } +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISDictionaryTest.java b/source/java/org/alfresco/cmis/dictionary/CMISDictionaryTest.java new file mode 100644 index 0000000000..bdc770429d --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISDictionaryTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +public class CMISDictionaryTest extends BaseCMISTest +{ + public void testBasicTypes() + { + cmisDictionaryService.setStrict(true); + for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds()) + { + System.out.println(name); + } + assertEquals(3, cmisDictionaryService.getAllObjectTypeIds().size()); + + } + + public void testBasicTypeDefinitions() + { + cmisDictionaryService.setStrict(false); + for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds()) + { + System.out.println(cmisDictionaryService.getType(name)); + } + + } + + public void testBasicProperties() + { + cmisDictionaryService.setStrict(false); + for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds()) + { + for (String propertyName : cmisDictionaryService.getPropertyDefinitions(name).keySet()) + { + System.out.println(name +" -> "+ propertyName); + } + } + + } + + public void testBasicPropertyDefinitions() + { + cmisDictionaryService.setStrict(true); + for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds()) + { + for (CMISPropertyDefinition proDef : cmisDictionaryService.getPropertyDefinitions(name).values()) + { + System.out.println(proDef); + } + } + + } +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISMapping.java b/source/java/org/alfresco/cmis/dictionary/CMISMapping.java new file mode 100644 index 0000000000..77bd8cc8cb --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISMapping.java @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +import java.util.Collection; +import java.util.HashMap; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * CMIS <-> Alfresco mappings + * + * @author andyh + */ +public class CMISMapping +{ + /** + * The Alfresco CMIS model URI. + */ + public static String CMIS_MODEL_URI = "http://www.alfresco.org/model/cmis/0.3"; + + /** + * The Alfresco CMIS Model name. + */ + public static String CMIS_MODEL_NAME = "cmismodel"; + + /** + * The QName for the Alfresco CMIS Model. + */ + public static QName CMIS_MODEL_QNAME = QName.createQName(CMIS_MODEL_URI, CMIS_MODEL_NAME); + + /** + * Type id for CMIS documents, from the spec. + */ + public static String DOCUMENT_OBJECT_TYPE = "DOCUMENT_OBJECT_TYPE"; + + /** + * Type is for CMIS folders, from the spec. + */ + public static String FOLDER_OBJECT_TYPE = "FOLDER_OBJECT_TYPE"; + + /** + * Type Id for CMIS Relationships, from the spec. + */ + public static String RELATIONSHIP_OBJECT_TYPE = "RELATIONSHIP_OBJECT_TYPE"; + + /** + * QName for CMIS documents in the Alfresco CMIS model. + */ + public static QName DOCUMENT_QNAME = QName.createQName(CMIS_MODEL_URI, DOCUMENT_OBJECT_TYPE); + + /** + * QName for CMIS folders in the Alfresco CMIS model + */ + public static QName FOLDER_QNAME = QName.createQName(CMIS_MODEL_URI, FOLDER_OBJECT_TYPE); + + /** + * QName for CMIS relationships in the the Alfresco CMIS model. + */ + public static QName RELATIONSHIP_QNAME = QName.createQName(CMIS_MODEL_URI, RELATIONSHIP_OBJECT_TYPE); + + + + // Mappings + // - no entry means no mapping and pass through as is + private static HashMap cmisTypeIdToTypeQName = new HashMap(); + + private static HashMap qNameToCmisTypeId = new HashMap(); + + private static HashMap cmisToAlfrecsoTypes = new HashMap(); + + private static HashMap alfrescoToCmisTypes = new HashMap(); + + private static HashMap alfrescoPropertyTypesToCimsPropertyTypes = new HashMap(); + /** + * Set up mappings + */ + static + { + cmisTypeIdToTypeQName.put(new CMISTypeId(DOCUMENT_OBJECT_TYPE), DOCUMENT_QNAME); + cmisTypeIdToTypeQName.put(new CMISTypeId(FOLDER_OBJECT_TYPE), FOLDER_QNAME); + cmisTypeIdToTypeQName.put(new CMISTypeId(RELATIONSHIP_OBJECT_TYPE), RELATIONSHIP_QNAME); + + qNameToCmisTypeId.put(DOCUMENT_QNAME, new CMISTypeId(DOCUMENT_OBJECT_TYPE)); + qNameToCmisTypeId.put(FOLDER_QNAME, new CMISTypeId(FOLDER_OBJECT_TYPE)); + qNameToCmisTypeId.put(RELATIONSHIP_QNAME, new CMISTypeId(RELATIONSHIP_OBJECT_TYPE)); + + cmisToAlfrecsoTypes.put(DOCUMENT_QNAME, ContentModel.TYPE_CONTENT); + cmisToAlfrecsoTypes.put(FOLDER_QNAME, ContentModel.TYPE_FOLDER); + cmisToAlfrecsoTypes.put(RELATIONSHIP_QNAME, null); + + alfrescoToCmisTypes.put(ContentModel.TYPE_CONTENT, DOCUMENT_QNAME); + alfrescoToCmisTypes.put(ContentModel.TYPE_FOLDER, FOLDER_QNAME); + + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.ANY, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.ASSOC_REF, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.BOOLEAN, CMISPropertyType.BOOLEAN); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.CATEGORY, CMISPropertyType.ID); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.CHILD_ASSOC_REF, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.CONTENT, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.DATE, CMISPropertyType.DATE_TIME); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.DATETIME, CMISPropertyType.DATE_TIME); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.DOUBLE, CMISPropertyType.DECIMAL); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.FLOAT, CMISPropertyType.DECIMAL); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.INT, CMISPropertyType.INTEGER); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.LOCALE, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.LONG, CMISPropertyType.INTEGER); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.MLTEXT, CMISPropertyType.STRING); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.NODE_REF, CMISPropertyType.ID); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.PATH, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.QNAME, null); + alfrescoPropertyTypesToCimsPropertyTypes.put(DataTypeDefinition.TEXT, CMISPropertyType.STRING); + + } + + /** + * Id this a CMIS core type defined in the Alfresco CMIS model + * + * @param typeQName + * @return + */ + public static boolean isCmisCoreType(QName typeQName) + { + return qNameToCmisTypeId.get(typeQName) != null; + } + + /** + * Get the CMIS Type Id given the Alfresco QName for the type in any Alfresco model + * + * @param typeQName + * @return + */ + public static CMISTypeId getCmisTypeId(QName typeQName) + { + CMISTypeId typeId = qNameToCmisTypeId.get(typeQName); + if (typeId == null) + { + return new CMISTypeId(typeQName.toString()); + } + else + { + return typeId; + } + } + + /** + * Given a type id - get the appropriate Alfresco QName + * + * @param typeId + * @return + */ + public static QName getTypeQname(CMISTypeId typeId) + { + QName typeQName = cmisTypeIdToTypeQName.get(typeId); + if (typeQName != null) + { + return typeQName; + } + else + { + return QName.createQName(typeId.getTypeId()); + } + } + + /** + * Get the query name for Alfresco qname + * + * @param namespaceService + * @param typeQName + * @return + */ + public static String getQueryName(NamespaceService namespaceService, QName typeQName) + { + return buildPrefixEncodedString(namespaceService, typeQName); + } + + private static String buildPrefixEncodedString(NamespaceService namespaceService, QName qname) + { + StringBuilder builder = new StringBuilder(128); + + if (!qname.getNamespaceURI().equals(CMIS_MODEL_URI)) + { + Collection prefixes = namespaceService.getPrefixes(qname.getNamespaceURI()); + if (prefixes.size() == 0) + { + throw new NamespaceException("A namespace prefix is not registered for uri " + qname.getNamespaceURI()); + } + String resolvedPrefix = prefixes.iterator().next(); + + builder.append(resolvedPrefix); + builder.append("_"); + } + + builder.append(qname.getLocalName()); + return builder.toString(); + } + + /** + * Is this a valid CMIS type The type must be a core CMIS type or extend cm:content or cm:folder The alfresco types + * cm:content and cm:folder are hidden by the CMIS types + * + * @param dictionaryService + * @param typeQName + * @return + */ + public static boolean isValidCmisType(DictionaryService dictionaryService, QName typeQName) + { + if (CMISMapping.isCmisCoreType(typeQName)) + { + return true; + } + + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT) || dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER)) + { + if (typeQName.equals(ContentModel.TYPE_CONTENT)) + { + return false; + } + else if (typeQName.equals(ContentModel.TYPE_FOLDER)) + { + return false; + } + + else + { + return true; + } + } + + return false; + } + + /** + * Is an association valid in CMIS? It must be a non-child relationship and the source and target must both be valid + * CMIS types. + * + * @param dictionaryService + * @param associationQName + * @return + */ + public static boolean isValidCmisAssociation(DictionaryService dictionaryService, QName associationQName) + { + AssociationDefinition associationDefinition = dictionaryService.getAssociation(associationQName); + if (associationDefinition == null) + { + return false; + } + if (associationDefinition.isChild()) + { + return false; + } + if (!isValidCmisType(dictionaryService, getCmisType(associationDefinition.getSourceClass().getName()))) + { + return false; + } + if (!isValidCmisType(dictionaryService, getCmisType(associationDefinition.getTargetClass().getName()))) + { + return false; + } + return true; + } + + /** + * Given an Alfresco model type map it to the appropriate type. Maps cm:folder and cm:content to the CMIS + * definitions + * + * @param typeQName + * @return + */ + public static QName getCmisType(QName typeQName) + { + QName mapped = alfrescoToCmisTypes.get(typeQName); + if (mapped != null) + { + return mapped; + } + return typeQName; + } + + /** + * Get the root CMIS object (in the alfresco model) for any type. + * + * @param dictionaryService + * @param typeQName + * @return + */ + public static QName getCmisRootType(DictionaryService dictionaryService, QName typeQName) + { + if (isCmisCoreType(typeQName)) + { + return typeQName; + } + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT)) + { + return DOCUMENT_QNAME; + } + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER)) + { + return FOLDER_QNAME; + } + if (isValidCmisAssociation(dictionaryService, typeQName)) + { + return RELATIONSHIP_QNAME; + } + throw new UnsupportedOperationException(); + + } + + public static String getCmisPropertyName(NamespaceService namespaceService, QName propertyQName) + { + return buildPrefixEncodedString(namespaceService, propertyQName); + } + + public static CMISPropertyType getPropertyType(DictionaryService dictionaryService, QName propertyQName) + { + PropertyDefinition propertyDefinition = dictionaryService.getProperty(propertyQName); + DataTypeDefinition dataTypeDefinition = propertyDefinition.getDataType(); + QName dQName = dataTypeDefinition.getName(); + if(propertyQName.getNamespaceURI().equals(CMIS_MODEL_URI) && dQName.equals(DataTypeDefinition.QNAME)) + { + return CMISPropertyType.TYPE_ID; + } + return alfrescoPropertyTypesToCimsPropertyTypes.get(dQName); + + } + + public static QName getPropertyQName(DictionaryService dictionaryService, NamespaceService namespaceService, String cmisPropertyName) + { + // Try the cmis model first - it it matches we are done + QName cmisPropertyQName = QName.createQName(CMIS_MODEL_URI, cmisPropertyName); + if(dictionaryService.getProperty(cmisPropertyQName) != null) + { + return cmisPropertyQName; + } + + int split = cmisPropertyName.indexOf('_'); + String prefix = cmisPropertyName.substring(0, split); + String localName = cmisPropertyName.substring(split+1); + + QName qname = QName.createQName(prefix, localName, namespaceService); + return qname; + + } +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISPropertyDefinition.java b/source/java/org/alfresco/cmis/dictionary/CMISPropertyDefinition.java new file mode 100644 index 0000000000..bc0fa9dff0 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISPropertyDefinition.java @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +import java.util.Collection; +import java.util.HashSet; + +import org.alfresco.repo.dictionary.IndexTokenisationMode; +import org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser; +import org.alfresco.repo.search.impl.lucene.analysis.DoubleAnalyser; +import org.alfresco.repo.search.impl.lucene.analysis.FloatAnalyser; +import org.alfresco.repo.search.impl.lucene.analysis.IntegerAnalyser; +import org.alfresco.repo.search.impl.lucene.analysis.LongAnalyser; +import org.alfresco.repo.search.impl.lucene.analysis.PathAnalyser; +import org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * A CMIS property definition + * + * @author andyh + */ +public class CMISPropertyDefinition +{ + private String propertyName; + + private String displayName; + + private String description; + + private CMISPropertyType propertyType; + + private CMISCardinality cardinality; + + private int maximumLength = -1; + + private String schemaURI = null; + + private String encoding = null; + + private Collection choices = new HashSet(); + + private boolean isOpenChoice = false; + + private boolean required; + + private String defaultValue; + + private CMISUpdatability updatability; + + private boolean queryable; + + private boolean orderable; + + public CMISPropertyDefinition(DictionaryService dictionaryService, NamespaceService namespaceService, QName propertyQName) + { + PropertyDefinition propDef = dictionaryService.getProperty(propertyQName); + if (propDef.getContainerClass().getName().equals(CMISMapping.RELATIONSHIP_QNAME)) + { + // Properties of associations - all the same + propertyName = CMISMapping.getCmisPropertyName(namespaceService, propertyQName); + displayName = propDef.getTitle(); + description = propDef.getDescription(); + propertyType = CMISMapping.getPropertyType(dictionaryService, propertyQName); + cardinality = propDef.isMultiValued() ? CMISCardinality.MULTI_VALUED : CMISCardinality.SINGLE_VALUED; + required = propDef.isMandatory(); + defaultValue = propDef.getDefaultValue(); + updatability = propDef.isProtected() ? CMISUpdatability.READ_ONLY : CMISUpdatability.READ_AND_WRITE; + queryable = false; + orderable = false; + } + else + { + + propertyName = CMISMapping.getCmisPropertyName(namespaceService, propertyQName); + displayName = propDef.getTitle(); + description = propDef.getDescription(); + propertyType = CMISMapping.getPropertyType(dictionaryService, propertyQName); + cardinality = propDef.isMultiValued() ? CMISCardinality.MULTI_VALUED : CMISCardinality.SINGLE_VALUED; + required = propDef.isMandatory(); + defaultValue = propDef.getDefaultValue(); + updatability = propDef.isProtected() ? CMISUpdatability.READ_ONLY : CMISUpdatability.READ_AND_WRITE; + queryable = propDef.isIndexed(); + IndexTokenisationMode indexTokenisationMode = IndexTokenisationMode.TRUE; + if(propDef.getIndexTokenisationMode() != null) + { + indexTokenisationMode = propDef.getIndexTokenisationMode(); + } + switch (indexTokenisationMode) + { + case BOTH: + case FALSE: + orderable = true; + break; + case TRUE: + default: + String analyserClassName = propDef.getDataType().getAnalyserClassName(); + if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()) + || analyserClassName.equals(DoubleAnalyser.class.getCanonicalName()) || analyserClassName.equals(FloatAnalyser.class.getCanonicalName()) + || analyserClassName.equals(IntegerAnalyser.class.getCanonicalName()) || analyserClassName.equals(LongAnalyser.class.getCanonicalName()) + || analyserClassName.equals(PathAnalyser.class.getCanonicalName()) || analyserClassName.equals(VerbatimAnalyser.class.getCanonicalName())) + { + orderable = true; + } + else + { + orderable = false; + } + } + } + + } + + /** + * Get the property name + * @return + */ + public String getPropertyName() + { + return propertyName; + } + + /** + * Get the display name + * @return + */ + public String getDisplayName() + { + return displayName; + } + + /** + * Get the description + * @return + */ + public String getDescription() + { + return description; + } + + /** + * Get the property type + * @return + */ + public CMISPropertyType getPropertyType() + { + return propertyType; + } + + /** + * Get the cardinality + * @return + */ + public CMISCardinality getCardinality() + { + return cardinality; + } + + /** + * For variable length properties, get the maximum length allowed. + * Unsupported. + * + * @return + */ + public int getMaximumLength() + { + return maximumLength; + } + + /** + * For properties of type CMISPropertyType.XML the schema to which the property must conform. Unsupported + * + * @return - the schema URI + */ + public String getSchemaURI() + { + return schemaURI; + } + + /** + * For properties of type CMISPropertyType.XML the encoding used for the property value + * + * @return the encoding + */ + public String getEncoding() + { + return encoding; + } + + /** + * Get the choices available as values for this property + * TODO: not implemented yet + * @return + */ + public Collection getChioces() + { + return choices; + } + + /** + * Is this a choice where a user can enter other values (ie a list with common options) + * @return + */ + public boolean isOpenChioce() + { + return isOpenChoice; + } + + /** + * Is this property required? + * @return + */ + public boolean isRequired() + { + return required; + } + + /** + * get the default value as a String + * + * @return + */ + public String getDefaultValue() + { + return defaultValue; + } + + /** + * Is this property updatable? + * @return + */ + public CMISUpdatability getUpdatability() + { + return updatability; + } + + /** + * Is this property queryable? + * @return + */ + public boolean isQueryable() + { + return queryable; + } + + /** + * Is this property orderable in queries? + * @return + */ + public boolean isOrderable() + { + return orderable; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("CMISPropertyDefinition["); + builder.append("PropertyName=").append(getPropertyName()).append(", "); + builder.append("DisplayName=").append(getDisplayName()).append(", "); + builder.append("Description=").append(getDescription()).append(", "); + builder.append("PropertyType=").append(getPropertyType()).append(", "); + builder.append("Cardinality=").append(getCardinality()).append(", "); + builder.append("MaximumLength=").append(getMaximumLength()).append(", "); + builder.append("SchemaURI=").append(getSchemaURI()).append(", "); + builder.append("Encoding=").append(getEncoding()).append(", "); + builder.append("Choices=").append(getChioces()).append(", "); + builder.append("IsOpenChoice=").append(isOpenChioce()).append(", "); + builder.append("Required=").append(isRequired()).append(", "); + builder.append("Default=").append(getDefaultValue()).append(", "); + builder.append("Updatable=").append(getUpdatability()).append(", "); + builder.append("Queryable=").append(isQueryable()).append(", "); + builder.append("Orderable=").append(isOrderable()); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISPropertyType.java b/source/java/org/alfresco/cmis/dictionary/CMISPropertyType.java new file mode 100644 index 0000000000..04b9b89fec --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISPropertyType.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +/** + * CMIS Property Types + * @author andyh + * + */ +public enum CMISPropertyType +{ + /** + * String + */ + STRING, + /** + * Decimal + */ + DECIMAL, + /** + * Integer + */ + INTEGER, + /** + * Boolean + */ + BOOLEAN, + /** + * Date-time + */ + DATE_TIME, + /** + * URI + */ + URI, + /** + * HTML + */ + HTML, + /** + * XML + */ + XML, + /** + * ID + */ + ID, + /** + * Type Id + */ + TYPE_ID; +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISPropertyValue.java b/source/java/org/alfresco/cmis/dictionary/CMISPropertyValue.java new file mode 100644 index 0000000000..a2868c4b52 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISPropertyValue.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +public interface CMISPropertyValue +{ + +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISTypeDefinition.java b/source/java/org/alfresco/cmis/dictionary/CMISTypeDefinition.java new file mode 100644 index 0000000000..f970571c27 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISTypeDefinition.java @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.cmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * The base type definition for CMIS + * + * @author andyh + */ +public class CMISTypeDefinition +{ + private CMISTypeId objectTypeId; + + private String objectTypeQueryName; + + private String displayName; + + private CMISTypeId parentTypeId; + + private String rootTypeQueryName; + + private String description; + + private boolean queryable; + + private boolean versionable; + + private String constraints = ""; + + private boolean isAssociation; + + private ArrayList allowedSourceTypes = new ArrayList(1); + + private ArrayList allowedTargetTypes = new ArrayList(1); + + public CMISTypeDefinition(DictionaryService dictionaryService, NamespaceService namespaceService, QName typeQName) + { + isAssociation = (typeQName.equals(CMISMapping.RELATIONSHIP_QNAME) || (dictionaryService.getAssociation(typeQName) != null)); + + if (isAssociation) + { + AssociationDefinition associationDefinition = dictionaryService.getAssociation(typeQName); + if (associationDefinition != null) + { + objectTypeId = CMISMapping.getCmisTypeId(typeQName); + objectTypeQueryName = CMISMapping.getQueryName(namespaceService, typeQName); + displayName = associationDefinition.getTitle(); + parentTypeId = CMISMapping.getCmisTypeId(CMISMapping.RELATIONSHIP_QNAME); + rootTypeQueryName = CMISMapping.getQueryName(namespaceService, CMISMapping.RELATIONSHIP_QNAME); + description = associationDefinition.getDescription(); + queryable = false; + versionable = false; + isAssociation = true; + allowedSourceTypes.add(CMISMapping.getCmisTypeId(CMISMapping.getCmisType(associationDefinition.getSourceClass().getName()))); + allowedTargetTypes.add(CMISMapping.getCmisTypeId(CMISMapping.getCmisType(associationDefinition.getTargetClass().getName()))); + } + else + { + // TODO: Add CMIS Association mapping?? + TypeDefinition typeDefinition = dictionaryService.getType(typeQName); + objectTypeId = CMISMapping.getCmisTypeId(typeQName); + objectTypeQueryName = CMISMapping.getQueryName(namespaceService, typeQName); + displayName = typeDefinition.getTitle(); + parentTypeId = CMISMapping.getCmisTypeId(CMISMapping.RELATIONSHIP_QNAME); + rootTypeQueryName = CMISMapping.getQueryName(namespaceService, CMISMapping.RELATIONSHIP_QNAME); + description = typeDefinition.getDescription(); + queryable = false; + versionable = false; + isAssociation = true; + } + } + else + { + TypeDefinition typeDefinition = dictionaryService.getType(typeQName); + if (typeDefinition != null) + { + objectTypeId = CMISMapping.getCmisTypeId(typeQName); + + objectTypeQueryName = CMISMapping.getQueryName(namespaceService, typeQName); + + displayName = typeDefinition.getTitle(); + + QName parentTypeQName = CMISMapping.getCmisType(typeDefinition.getParentName()); + if (parentTypeQName == null) + { + // Core and unknown types + parentTypeId = null; + } + else + { + if (CMISMapping.isValidCmisType(dictionaryService, typeQName)) + { + parentTypeId = CMISMapping.getCmisTypeId(parentTypeQName); + } + } + + rootTypeQueryName = CMISMapping.getQueryName(namespaceService, CMISMapping.getCmisRootType(dictionaryService, typeQName)); + + description = typeDefinition.getDescription(); + + queryable = true; + + versionable = false; + List defaultAspects = typeDefinition.getDefaultAspects(); + for (AspectDefinition aspectDefinition : defaultAspects) + { + if (aspectDefinition.getName().equals(ContentModel.ASPECT_VERSIONABLE)) + { + versionable = true; + break; + } + } + } + + } + + } + + /** + * Get the unique identifier for the type + * + * @return - the type id + */ + public CMISTypeId getObjectTypeId() + { + return objectTypeId; + } + + /** + * Get the table name used for queries against the type. This is also a unique identifier for the type. The string + * conforms to SQL table naming conventions. TODO: Should we impose a maximum length and if so how do we avoid + * collisions from truncations? + * + * @return the sql table name + */ + public String getObjectTypeQueryName() + { + return objectTypeQueryName; + } + + /** + * Get the display name for the type. + * + * @return - the display name + */ + public String getObjectTypeDisplayName() + { + return displayName; + } + + /** + * Get the type id for the parent + * + * @return - the parent type id + */ + public CMISTypeId getParentTypeId() + { + return parentTypeId; + } + + /** + * Get the sql table name for the root type of this type This will be getObjectTypeQueryName() for the base folder, + * document or association + * + * @return - the sql table name for the root type + */ + public String getRootTypeQueryName() + { + return rootTypeQueryName; + } + + /** + * Get the description for the type + * + * @return - the description + */ + public String getDescription() + { + return description; + } + + /** + * Is this type queryable? If not, the type may not appear in the FROM clause of a query. This property of the type + * is not inherited in the type hierarchy. It is set on each type. + * + * @return true if queryable + */ + public boolean isQueryable() + { + return queryable; + } + + /** + * Is this type versionable? If true this implies all instances of the type are versionable. + * + * @return true if versionable + */ + public boolean isVersionable() + { + return versionable; + } + + /** + * Get the constraints for the type. These are not currently supported. + * + * @return + */ + public String getConstraints() + { + return constraints; + } + + /** + * Is this an association type? + * + * @return true for an association type. + */ + public boolean isAssociation() + { + return isAssociation; + } + + /** + * For an association, get the collection of valid source types. For non-associations the collection will be empty. + * + * @return + */ + public Collection getAllowedSourceTypes() + { + return allowedSourceTypes; + } + + /** + * For an association, get the collection of valid target types. For non-associations the collection will be empty. + * + * @return + */ + public Collection getAllowedTargetTypes() + { + return allowedTargetTypes; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("CMISTypeDefinition["); + builder.append("ObjectTypeId=").append(getObjectTypeId()).append(", "); + builder.append("ObjectTypeQueryName=").append(getObjectTypeQueryName()).append(", "); + builder.append("ObjectTypeDisplayName=").append(getObjectTypeDisplayName()).append(", "); + builder.append("ParentTypeId=").append(getParentTypeId()).append(", "); + builder.append("RootTypeQueryName=").append(getRootTypeQueryName()).append(", "); + builder.append("Description=").append(getDescription()).append(", "); + builder.append("Queryable=").append(isQueryable()).append(", "); + builder.append("Versionable=").append(isVersionable()).append(", "); + builder.append("Constraints=").append(getConstraints()).append(", "); + builder.append("IsAssociation=").append(isAssociation()).append(", "); + builder.append("AllowedSourceTypes=").append(getAllowedSourceTypes()).append(", "); + builder.append("AllowedTargetTypes=").append(getAllowedTargetTypes()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISTypeId.java b/source/java/org/alfresco/cmis/dictionary/CMISTypeId.java new file mode 100644 index 0000000000..610a8ceb40 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISTypeId.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +public class CMISTypeId implements CMISPropertyValue +{ + private String typeId; + + public CMISTypeId(String typeId) + { + this.typeId = typeId; + } + + public String getTypeId() + { + return typeId; + } + + public String toString() + { + return getTypeId(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((typeId == null) ? 0 : typeId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final CMISTypeId other = (CMISTypeId) obj; + if (typeId == null) + { + if (other.typeId != null) + return false; + } + else if (!typeId.equals(other.typeId)) + return false; + return true; + } + + +} diff --git a/source/java/org/alfresco/cmis/dictionary/CMISUpdatability.java b/source/java/org/alfresco/cmis/dictionary/CMISUpdatability.java new file mode 100644 index 0000000000..312d32e462 --- /dev/null +++ b/source/java/org/alfresco/cmis/dictionary/CMISUpdatability.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.dictionary; + +public enum CMISUpdatability +{ + READ_ONLY, READ_AND_WRITE, READ_AND_WRITE_WHEN_CHECKED_OUT; +} diff --git a/source/java/org/alfresco/repo/dictionary/CompiledModel.java b/source/java/org/alfresco/repo/dictionary/CompiledModel.java index ebcea6d9e4..91cb837f4d 100644 --- a/source/java/org/alfresco/repo/dictionary/CompiledModel.java +++ b/source/java/org/alfresco/repo/dictionary/CompiledModel.java @@ -404,6 +404,15 @@ import org.apache.commons.logging.LogFactory; return associations.get(name); } + /** + * @return the compiled associations + */ + public Collection getAssociations() + { + return associations.values(); + } + + /* (non-Javadoc) * @see org.alfresco.repo.dictionary.impl.ModelQuery#getConstraint(QName) */ diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java b/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java index 8aa908a603..7446deb8f0 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java @@ -161,6 +161,19 @@ public class DictionaryComponent implements DictionaryService, TenantDeployer } return aspects; } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAllAssociations() + */ + public Collection getAllAssociations() + { + Collection associations = new ArrayList(64); + for (QName model : getAllModels()) + { + associations.addAll(getAssociations(model)); + } + return associations; + } /* (non-Javadoc) @@ -185,6 +198,20 @@ public class DictionaryComponent implements DictionaryService, TenantDeployer } return qnames; } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAssociations(org.alfresco.repo.ref.QName) + */ + public Collection getAssociations(QName model) + { + Collection associations = dictionaryDAO.getAssociations(model); + Collection qnames = new ArrayList(associations.size()); + for (AssociationDefinition def : associations) + { + qnames.add(def.getName()); + } + return qnames; + } /* (non-Javadoc) diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java index 330efea401..f57f1edbb2 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java @@ -27,6 +27,7 @@ package org.alfresco.repo.dictionary; import java.util.Collection; import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.ModelDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.NamespaceDefinition; @@ -79,6 +80,13 @@ public interface DictionaryDAO extends ModelQuery */ public Collection getAspects(QName model); + + /** + * @param model the model to retrieve associations for + * @return the associations of the model + */ + public Collection getAssociations(QName model); + /** * @param superAspect * @param follow true => follow up the super-class hierarchy, false => immediate sub aspects only diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java index 827af87cc2..58eb58f6b2 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java @@ -688,6 +688,12 @@ public class DictionaryDAOImpl implements DictionaryDAO return null; } + public Collection getAssociations(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + return model.getAssociations(); + } + /* (non-Javadoc) * @see org.alfresco.repo.dictionary.impl.DictionaryDAO#getModels() diff --git a/source/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java b/source/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java new file mode 100644 index 0000000000..f7ae53df77 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.dictionary; + +/** + * How tokenisation is supported in the index. + * + * + * @author andyh + * + */ +public enum IndexTokenisationMode { + /** + * Tokenise the property. If the analyser supported ordering then the field + * supports ordering FTS is supported via analysis. + */ + TRUE, + /** + * Do not tokenise the property. The field supports ordering and pattern + * matching. + */ + FALSE, + /** + * There may be two indexes - one to support ordering and one to support + * search. + */ + BOTH; + + public static String serializer(IndexTokenisationMode indexTokenisationMode) { + return indexTokenisationMode.toString(); + } + + public static IndexTokenisationMode deserializer(String value) { + if (value == null) { + return null; + } else if (value.equalsIgnoreCase(TRUE.toString())) { + return TRUE; + } else if (value.equalsIgnoreCase(FALSE.toString())) { + return FALSE; + } else if (value.equalsIgnoreCase(BOTH.toString())) { + return BOTH; + } else { + throw new IllegalArgumentException( + "Invalid IndexTokenisationMode: " + value); + } + } +} diff --git a/source/java/org/alfresco/repo/dictionary/M2Property.java b/source/java/org/alfresco/repo/dictionary/M2Property.java index a14e4ccd91..ba06ca00d6 100644 --- a/source/java/org/alfresco/repo/dictionary/M2Property.java +++ b/source/java/org/alfresco/repo/dictionary/M2Property.java @@ -50,7 +50,7 @@ public class M2Property private boolean isIndexed = true; private boolean isIndexedAtomically = true; private boolean isStoredInIndex = false; - private boolean isTokenisedInIndex = true; + private IndexTokenisationMode indexTokenisationMode = IndexTokenisationMode.TRUE; private List constraints; /*package*/ M2Property() @@ -204,15 +204,15 @@ public class M2Property } - public boolean isTokenisedInIndex() + public IndexTokenisationMode getIndexTokenisationMode() { - return isTokenisedInIndex; + return indexTokenisationMode; } - public void setTokenisedInIndex(boolean isTokenisedInIndex) + public void setIndexTokenisationMode(IndexTokenisationMode indexTokenisationMode) { - this.isTokenisedInIndex = isTokenisedInIndex; + this.indexTokenisationMode = indexTokenisationMode; } diff --git a/source/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java b/source/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java index 26c5f718f9..d9c5a447e0 100644 --- a/source/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java +++ b/source/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java @@ -214,7 +214,7 @@ import org.alfresco.service.namespace.QName; property.setProtected(propertyDef.isProtected()); property.setStoredInIndex(propertyDef.isStoredInIndex()); property.setTitle(propertyDef.getTitle()); - property.setTokenisedInIndex(propertyDef.isTokenisedInIndex()); + property.setIndexTokenisationMode(propertyDef.getIndexTokenisationMode()); return property; } @@ -240,7 +240,7 @@ import org.alfresco.service.namespace.QName; sb.append("isIndexed: " + isIndexed() + "\n"); sb.append("isStoredInIndex: " + isStoredInIndex() + "\n"); sb.append("isIndexedAtomically: " + isIndexedAtomically() + "\n"); - sb.append("isTokenisedInIndex: " + isTokenisedInIndex() + "\n"); + sb.append("indexTokenisationMode: " + getIndexTokenisationMode() + "\n"); return sb.toString(); } @@ -378,9 +378,9 @@ import org.alfresco.service.namespace.QName; /* (non-Javadoc) * @see org.alfresco.repo.dictionary.PropertyDefinition#isTokenisedInIndex() */ - public boolean isTokenisedInIndex() + public IndexTokenisationMode getIndexTokenisationMode() { - return m2Property.isTokenisedInIndex(); + return m2Property.getIndexTokenisationMode(); } diff --git a/source/java/org/alfresco/repo/dictionary/m2binding.xml b/source/java/org/alfresco/repo/dictionary/m2binding.xml index b24e31c3ce..01b6641f8b 100644 --- a/source/java/org/alfresco/repo/dictionary/m2binding.xml +++ b/source/java/org/alfresco/repo/dictionary/m2binding.xml @@ -114,7 +114,7 @@ - + diff --git a/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java b/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java index 9eda94ba6a..da7e8a8fe3 100644 --- a/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java +++ b/source/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java @@ -57,6 +57,7 @@ import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.AbstractContentTransformerTest; import org.alfresco.repo.content.transform.ContentTransformerRegistry; import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.dictionary.IndexTokenisationMode; import org.alfresco.repo.dictionary.M2Aspect; import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.M2Property; @@ -224,7 +225,7 @@ public class RuleServiceCoverageTest extends TestCase genCatProp.setMandatory(true); genCatProp.setMultiValued(true); genCatProp.setStoredInIndex(true); - genCatProp.setTokenisedInIndex(true); + genCatProp.setIndexTokenisationMode(IndexTokenisationMode.TRUE); genCatProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName()); // Save the mode diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java index 7427456857..39414c4a06 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java @@ -39,6 +39,7 @@ import junit.framework.TestCase; import org.alfresco.model.ContentModel; import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.dictionary.IndexTokenisationMode; import org.alfresco.repo.dictionary.M2Aspect; import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.M2Property; @@ -286,7 +287,7 @@ public class ADMLuceneCategoryTest extends TestCase genCatProp.setMandatory(true); genCatProp.setMultiValued(true); genCatProp.setStoredInIndex(true); - genCatProp.setTokenisedInIndex(false); + genCatProp.setIndexTokenisationMode(IndexTokenisationMode.FALSE); genCatProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName()); assetClassCategorisationQName = QName.createQName(TEST_NAMESPACE, "assetClass"); @@ -298,7 +299,7 @@ public class ADMLuceneCategoryTest extends TestCase acProp.setMandatory(true); acProp.setMultiValued(true); acProp.setStoredInIndex(true); - acProp.setTokenisedInIndex(false); + acProp.setIndexTokenisationMode(IndexTokenisationMode.FALSE); acProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName()); investmentRegionCategorisationQName = QName.createQName(TEST_NAMESPACE, "investmentRegion"); @@ -310,7 +311,7 @@ public class ADMLuceneCategoryTest extends TestCase irProp.setMandatory(true); irProp.setMultiValued(true); irProp.setStoredInIndex(true); - irProp.setTokenisedInIndex(false); + irProp.setIndexTokenisationMode(IndexTokenisationMode.FALSE); irProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName()); marketingRegionCategorisationQName = QName.createQName(TEST_NAMESPACE, "marketingRegion"); @@ -322,7 +323,7 @@ public class ADMLuceneCategoryTest extends TestCase mrProp.setMandatory(true); mrProp.setMultiValued(true); mrProp.setStoredInIndex(true); - mrProp.setTokenisedInIndex(false); + mrProp.setIndexTokenisationMode(IndexTokenisationMode.FALSE); mrProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName()); dictionaryDAO.putModel(model); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java index f22db494ab..f0bed4513a 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java @@ -51,9 +51,9 @@ import org.alfresco.repo.avm.util.SimplePath; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.dictionary.IndexTokenisationMode; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.search.IndexMode; -import org.alfresco.repo.search.Indexer; import org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser; import org.alfresco.repo.search.impl.lucene.fts.FTSIndexerAware; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; @@ -677,7 +677,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl boolean store = true; boolean index = true; - boolean tokenise = true; + IndexTokenisationMode tokenise = IndexTokenisationMode.TRUE; @SuppressWarnings("unused") boolean atomic = true; boolean isContent = false; @@ -690,7 +690,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl { index = propertyDef.isIndexed(); store = propertyDef.isStoredInIndex(); - tokenise = propertyDef.isTokenisedInIndex(); + tokenise = propertyDef.getIndexTokenisationMode(); atomic = propertyDef.isIndexedAtomically(); isContent = propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT); isMultiLingual = propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT); @@ -874,21 +874,22 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl Field.Store fieldStore = store ? Field.Store.YES : Field.Store.NO; Field.Index fieldIndex; - if (index) + if (index) { - if (tokenise) - { - fieldIndex = Field.Index.TOKENIZED; - } - else - { - fieldIndex = Field.Index.UN_TOKENIZED; - } - } - else - { - fieldIndex = Field.Index.NO; - } + switch (tokenise) { + case TRUE: + case BOTH: + default: + fieldIndex = Field.Index.TOKENIZED; + break; + case FALSE: + fieldIndex = Field.Index.UN_TOKENIZED; + break; + + } + } else { + fieldIndex = Field.Index.NO; + } if ((fieldIndex != Field.Index.NO) || (fieldStore != Field.Store.NO)) { @@ -926,15 +927,26 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl { locale = I18NUtil.getLocale(); } - if (tokenise) + + StringBuilder builder; + switch(tokenise) { - StringBuilder builder = new StringBuilder(); + default: + case TRUE: + builder = new StringBuilder(); builder.append("\u0000").append(locale.toString()).append("\u0000").append(strValue); doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, Field.TermVector.NO)); - } - else - { + break; + case FALSE: + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + break; + case BOTH: + builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000").append(strValue); + doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, Field.TermVector.NO)); + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + break; } } else if (isDateTime) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java index b4039b7723..f16250c0f4 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.model.ContentModel; +import org.alfresco.repo.dictionary.IndexTokenisationMode; import org.alfresco.repo.search.MLAnalysisMode; import org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser; import org.alfresco.repo.search.impl.lucene.analysis.LongAnalyser; @@ -178,7 +179,7 @@ public class LuceneAnalyser extends Analyzer PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName); if (propertyDef != null) { - if (propertyDef.isTokenisedInIndex()) + if ((propertyDef.getIndexTokenisationMode() == IndexTokenisationMode.BOTH) || (propertyDef.getIndexTokenisationMode() == IndexTokenisationMode.TRUE)) { DataTypeDefinition dataType = propertyDef.getDataType(); if (dataType.getName().equals(DataTypeDefinition.CONTENT)) diff --git a/source/java/org/alfresco/repo/search/impl/parsers/CMIS.g b/source/java/org/alfresco/repo/search/impl/parsers/CMIS.g new file mode 100644 index 0000000000..684bfb4914 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/parsers/CMIS.g @@ -0,0 +1,568 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +/* + * Parser for the CMIS query language + * + * The semantics of multivalued properties are ignored for the initial parse of the language. + * They are applied in a second pass, when we have enough information to determine the column type. + */ + +grammar CMIS; + +options +{ + output=AST; +} + +tokens +{ + QUERY; + ALL_COLUMNS; + COLUMN; + COLUMNS; + COLUMN_REF; + QUALIFIER; + STRING_FUNCTION; + NUMERIC_FUNCTION; + SOURCE; + TABLE; + TABLE_REF; + PARAMETER; + + CONJUNCTION; + DISJUNCTION; + NEGATION; + PRED_COMPARISON; + PRED_IN; + PRED_EXISTS; + PRED_LIKE; + PRED_FTS; + LIST; + PRED_CHILD; + PRED_DESCENDANT; + SORT_SPECIFICATION; + + NUMERIC_LITERAL; + STRING_LITERAL; +} + +/* + * Instance methods and properties for the parser. + * Realisations of the parser should over-ride these as required + */ + +@members +{ + /** + * CMIS strict + */ + public boolean strict() + { + return true; + } +} + +/** + * This is mostly a direct take fom the CMIS spec. + * The only significant chnanges are to remove left recursion which is not supported in antlr + * + * The top level rule for the parser + */ +query + : SELECT selectList fromClause whereClause? orderByClause? + -> ^(QUERY selectList fromClause whereClause? orderByClause?) + ; + + +selectList + : STAR + -> ^(ALL_COLUMNS) + | selectSubList ( COMMA selectSubList )* + -> ^(COLUMNS selectSubList+) + ; + + +selectSubList + : (valueExpression)=> valueExpression ( AS? columnName )? + -> ^(COLUMN valueExpression columnName?) + | qualifier DOTSTAR + -> ^(ALL_COLUMNS qualifier) + | multiValuedColumnReference + -> /* No AST - MVCs are included in value expressions */ + ; + +valueExpression + : columnReference + -> columnReference + | stringValueFunction + -> stringValueFunction + | numericValueFunction + -> numericValueFunction + ; + +columnReference + : ( qualifier DOT )? columnName + -> ^(COLUMN_REF columnName qualifier?) + ; + +/* + * This production is proteted by a dynamic predicate. + * TODO Add look a head and perform the test + */ +multiValuedColumnReference + : ( qualifier DOT )? multiValuedColumnName + -> ^(COLUMN_REF multiValuedColumnName qualifier?) + ; + +stringValueFunction + : ( functionName=UPPER | functionName=LOWER ) LPAREN columnReference RPAREN + -> ^(STRING_FUNCTION $functionName columnReference) + ; + +numericValueFunction + : functionName=SCORE LPAREN qualifier? RPAREN + -> ^(NUMERIC_FUNCTION $functionName qualifier?) + ; + +qualifier + : (tableName) => tableName + -> tableName + | correlationName + -> correlationName + ; + +fromClause + : FROM tableReference + -> tableReference + ; + +tableReference + : singleTable ((joinedTable) => joinedTable)* + -> ^(SOURCE singleTable joinedTable*) + ; + +/* + * Created to avoid left recursion between tableReference and joinedTable. + */ +singleTable + : tableName ( AS? correlationName )? + -> ^(TABLE_REF tableName correlationName?) + | LPAREN joinedTables RPAREN + -> ^(TABLE joinedTables) + ; + +joinedTable + : joinType? JOIN tableReference ((joinSpecification) => joinSpecification)? + -> ^(JOIN tableReference joinType? joinSpecification?) + ; + + +joinedTables + : singleTable joinedTable+ + -> singleTable joinedTable+ + ; + +joinType + : INNER + -> INNER + | LEFT OUTER? + -> LEFT OUTER? + ; + +joinSpecification + : ON LPAREN lhs=columnReference EQUALS rhs=columnReference RPAREN + -> ^(ON $lhs EQUALS $rhs) + ; + + +/* + * Broken out the left recursion from the spec + */ +whereClause + : WHERE searchOrCondition + -> searchOrCondition + ; + +/** + * Broken left recursion. + */ +searchOrCondition + : searchAndCondition (OR searchAndCondition)* + -> ^(DISJUNCTION searchAndCondition+) + ; + + +/** + * Broken left recursion. + */ +searchAndCondition + : searchNotCondition (AND searchNotCondition)* + -> ^(CONJUNCTION searchNotCondition+) + ; + +searchNotCondition + : NOT searchTest + -> ^(NEGATION searchTest) + | searchTest + -> searchTest + ; + +searchTest + : predicate + -> predicate + | LPAREN searchOrCondition RPAREN + -> searchOrCondition + ; + +predicate + : comparisonPredicate + | inPredicate + | likePredicate + | nullPredicate + | quantifiedComparisonPredicate + | quantifiedInPredicate + | textSearchPredicate + | folderPredicate + ; + +comparisonPredicate + : valueExpression compOp literalOrParameterName + -> ^(PRED_COMPARISON ANY valueExpression compOp literalOrParameterName) + ; + +compOp + : EQUALS + | NOTEQUALS + | LESSTHAN + | GREATERTHAN + | LESSTHANOREQUALS + | GREATERTHANOREQUALS + ; + +literalOrParameterName + : literal + | parameterName + ; + +literal + : signedNumericLiteral + | characterStringLiteral + ; + +inPredicate + : columnReference NOT? IN LPAREN inValueList RPAREN + -> ^(PRED_IN ANY columnReference NOT? inValueList) + ; + +inValueList + : literalOrParameterName (COMMA literalOrParameterName )* + -> ^(LIST literalOrParameterName+) + ; + +likePredicate + : columnReference NOT? LIKE characterStringLiteral + -> ^(PRED_LIKE columnReference NOT? characterStringLiteral) + ; + +nullPredicate + : ( (columnReference)=> columnReference | multiValuedColumnReference) IS NOT? NULL + -> ^(PRED_EXISTS columnReference NOT?) + ; + +quantifiedComparisonPredicate + : literalOrParameterName compOp ANY multiValuedColumnReference + -> ^(PRED_COMPARISON ANY literalOrParameterName compOp multiValuedColumnReference) + ; + + +quantifiedInPredicate + : ANY multiValuedColumnReference NOT? IN LPAREN inValueList RPAREN + -> ^(PRED_IN ANY multiValuedColumnReference NOT? inValueList) + ; + +textSearchPredicate + : CONTAINS LPAREN (qualifier COMMA | COMMA)? textSearchExpression RPAREN + -> ^(PRED_FTS textSearchExpression qualifier) + ; + +folderPredicate + : IN_FOLDER folderPredicateArgs + -> ^(PRED_CHILD folderPredicateArgs) + | IN_TREE folderPredicateArgs + -> ^(PRED_DESCENDANT folderPredicateArgs) + ; + +folderPredicateArgs + : LPAREN (qualifier COMMA | COMMA)? folderId RPAREN + -> folderId qualifier? + ; + +orderByClause + : ORDER BY sortSpecification ( COMMA sortSpecification )* + -> ^(ORDER sortSpecification+) + ; + +sortSpecification + : columnName + -> ^(SORT_SPECIFICATION columnName ASC) + | columnName ( by=ASC | by=DESC ) + -> ^(SORT_SPECIFICATION columnName $by) + ; + +correlationName + : identifier + ; + +/* + * Parse time validation of the table name + * TODO wire up the look a head + */ +tableName + : identifier + -> identifier + ; + +columnName + : identifier + -> identifier + ; + +multiValuedColumnName + : identifier + -> identifier + ; + +parameterName + : COLON identifier + -> ^(PARAMETER identifier) + ; + +folderId + : characterStringLiteral + -> characterStringLiteral + ; + +textSearchExpression + : QUOTED_STRING + ; + +identifier + : ID + -> ID + | DOUBLE_QUOTE keyWordOrId DOUBLE_QUOTE + -> ^(keyWordOrId) + ; + +signedNumericLiteral + : FLOATING_POINT_LITERAL + -> ^(NUMERIC_LITERAL FLOATING_POINT_LITERAL) + | integerLiteral + -> integerLiteral + ; + +integerLiteral + : DECIMAL_INTEGER_LITERAL + -> ^(NUMERIC_LITERAL DECIMAL_INTEGER_LITERAL) + ; + +characterStringLiteral + : QUOTED_STRING + -> ^(STRING_LITERAL QUOTED_STRING) + ; + + +keyWord : SELECT + | AS + | UPPER + | LOWER + | FROM + | JOIN + | INNER + | LEFT + | OUTER + | ON + | WHERE + | OR + | AND + | NOT + | IN + | LIKE + | IS + | NULL + | ANY + | CONTAINS + | IN_FOLDER + | IN_TREE + | ORDER + | BY + | ASC + | DESC + | SCORE + ; + +keyWordOrId + : keyWord + -> keyWord + | ID + -> ID + ; + +/* + * LEXER + */ + +SELECT : ('S'|'s')('E'|'e')('L'|'l')('E'|'e')('C'|'c')('T'|'t'); +AS : ('A'|'a')('S'|'s'); +UPPER : ('U'|'u')('P'|'p')('P'|'p')('E'|'e')('R'|'r'); +LOWER : ('L'|'l')('O'|'o')('W'|'w')('E'|'e')('R'|'r'); +FROM : ('F'|'f')('R'|'r')('O'|'o')('M'|'m'); +JOIN : ('J'|'j')('O'|'o')('I'|'i')('N'|'n'); +INNER : ('I'|'i')('N'|'n')('N'|'n')('E'|'e')('R'|'r'); +LEFT : ('L'|'l')('E'|'e')('F'|'f')('T'|'t'); +OUTER : ('O'|'o')('U'|'u')('T'|'t')('E'|'e')('R'|'r'); +ON : ('O'|'o')('N'|'n'); +WHERE : ('W'|'w')('H'|'h')('E'|'e')('R'|'r')('E'|'e'); +OR : ('O'|'o')('R'|'r'); +AND : ('A'|'a')('N'|'n')('D'|'d'); +NOT : ('N'|'n')('O'|'o')('T'|'t'); +IN : ('I'|'i')('N'|'n'); +LIKE : ('L'|'l')('I'|'i')('K'|'k')('E'|'e'); +IS : ('I'|'i')('S'|'s'); +NULL : ('N'|'n')('U'|'u')('L'|'l')('L'|'l'); +ANY : ('A'|'a')('N'|'n')('Y'|'y'); +CONTAINS: ('C'|'c')('O'|'o')('N'|'n')('T'|'t')('A'|'a')('I'|'i')('N'|'n')('S'|'s'); +IN_FOLDER + : ('I'|'i')('N'|'n')'_'('F'|'f')('O'|'o')('L'|'l')('D'|'d')('E'|'e')('R'|'r'); +IN_TREE : ('I'|'i')('N'|'n')'_'('T'|'t')('R'|'r')('E'|'e')('E'|'e'); +ORDER : ('O'|'o')('R'|'r')('D'|'d')('E'|'e')('R'|'r'); +BY : ('B'|'b')('Y'|'y'); +ASC : ('A'|'a')('S'|'s')('C'|'c'); +DESC : ('D'|'d')('E'|'e')('S'|'s')('C'|'c'); +SCORE : ('S'|'s')('C'|'c')('O'|'o')('R'|'r')('E'|'e'); +LPAREN : '(' ; +RPAREN : ')' ; +STAR : '*' ; +COMMA : ',' ; +DOTSTAR : '.*' ; +DOT : '.' ; +DOTDOT : '..' ; +EQUALS : '=' ; +TILDA : '~' ; +NOTEQUALS + : '<>' ; +GREATERTHAN + : '>' ; +LESSTHAN + : '<' ; +GREATERTHANOREQUALS + : '>=' ; +LESSTHANOREQUALS + : '<=' ; +COLON : ':' ; + +SINGLE_QUOTE + : '\''; + +DOUBLE_QUOTE + : '"' + ; + +QUOTED_STRING + : SINGLE_QUOTE ( ~SINGLE_QUOTE | ESCAPED_SINGLE_QUOTE)* SINGLE_QUOTE + ; + + +/* + * Decimal adapted from the Java spec + */ +DECIMAL_INTEGER_LITERAL + : ( PLUS | MINUS )? DECIMAL_NUMERAL + ; + +/* + * Floating point adapted from the Java spec + */ +FLOATING_POINT_LITERAL + : DIGIT+ DOT DIGIT* EXPONENT? + | DOT DIGIT+ EXPONENT? + | DIGIT+ EXPONENT + ; + + +ID : ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'0'..'0'|'_'|'$'|'#')* ; +WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; } ; + +/* + * Fragments for quoted strings + */ + +fragment +ESCAPED_SINGLE_QUOTE + : '\'\''; + +/** + * Fragments for decimal + */ + +fragment +DECIMAL_NUMERAL + : ZERO_DIGIT + | NON_ZERO_DIGIT DIGIT* + ; +fragment +DIGIT : ZERO_DIGIT | NON_ZERO_DIGIT ; +fragment +ZERO_DIGIT + : '0' ; +fragment +NON_ZERO_DIGIT + : '1'..'9' ; +fragment +PLUS : '+' ; +fragment +MINUS : '-' ; + +fragment +E : ('e' | 'E') ; + + + + +/* + * Fragments for floating point + */ + +fragment +EXPONENT + : E SIGNED_INTEGER + ; +fragment +SIGNED_INTEGER + : (PLUS | MINUS)? DIGIT+ + ; + + + diff --git a/source/java/org/alfresco/repo/search/impl/parsers/FTS.g b/source/java/org/alfresco/repo/search/impl/parsers/FTS.g new file mode 100644 index 0000000000..55cb00978b --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/parsers/FTS.g @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +/* + * Parser for the CMIS query language + * + * The semantics of multivalued properties are ignored for the initial parse of the language. + * They are applied in a second pass, when we have enough information to determine the column type. + */ + +grammar FTS; + +options +{ + output=AST; +} + +tokens +{ + FTS; + DISJUNCTION; + CONJUNCTION; + NEGATION; + TERM; + EXACT_TERM; + PHRASE; + SYNONYM; + + FIELD_DISJUNCTION; + FIELD_CONJUNCTION; + FIELD_NEGATION; + FIELD_GROUP; + FG_TERM; + FG_EXACT_TERM; + FG_PHRASE; + FG_SYNONYM; + FG_PROXIMITY; + FG_RANGE; + + COLUMN_REF; +} + +@members +{ + + public boolean defaultConjunction() + { + return true; + } + + public boolean defaultFieldConjunction() + { + return true; + } + + +} + +fts : ftsImplicitConjunctionOrDisjunction + -> ftsImplicitConjunctionOrDisjunction + ; + +ftsImplicitConjunctionOrDisjunction + : {defaultConjunction()}? ftsExplicitDisjunction (ftsExplicitDisjunction)* + -> ^(CONJUNCTION ftsExplicitDisjunction+) + | ftsExplicitDisjunction (ftsExplicitDisjunction)* + -> ^(DISJUNCTION ftsExplicitDisjunction+) + ; + +ftsExplicitDisjunction + : ftsExplictConjunction (OR ftsExplictConjunction)* + -> ^(DISJUNCTION ftsExplictConjunction+) + ; + +ftsExplictConjunction + : ftsNot (AND ftsNot)* + -> ^(CONJUNCTION ftsNot) + ; + + +ftsNot : MINUS ftsTest + -> ^(NEGATION ftsTest) + | ftsTest + -> ftsTest + ; + +ftsTest : ftsTerm + -> ^(TERM ftsTerm) + | ftsExactTerm + -> ^(EXACT_TERM ftsExactTerm) + | ftsPhrase + -> ^(PHRASE ftsPhrase) + | ftsSynonym + -> ^(SYNONYM ftsSynonym) + | ftsFieldGroupProximity + -> ^(FG_PROXIMITY ftsFieldGroupProximity) + | ftsFieldGroupRange + -> ^(FG_RANGE ftsFieldGroupRange) + | ftsFieldGroup + | LPAREN ftsImplicitConjunctionOrDisjunction RPAREN + -> ftsImplicitConjunctionOrDisjunction + ; + +ftsTerm + : (columnReference COLON)? FTSWORD + -> FTSWORD columnReference? + ; + +ftsExactTerm + : PLUS ftsTerm + -> ftsTerm + ; + +ftsPhrase + : (columnReference COLON)? FTSPHRASE + -> FTSPHRASE columnReference? + ; + +ftsSynonym + : TILDA ftsTerm + -> ftsTerm + ; + + +ftsFieldGroup + : columnReference COLON LPAREN ftsFieldGroupImplicitConjunctionOrDisjunction RPAREN + -> ^(FIELD_GROUP columnReference ftsFieldGroupImplicitConjunctionOrDisjunction) + ; + +ftsFieldGroupImplicitConjunctionOrDisjunction + : {defaultFieldConjunction}? ftsFieldGroupExplicitDisjunction (ftsFieldGroupExplicitDisjunction)* + -> ^(FIELD_CONJUNCTION ftsFieldGroupExplicitDisjunction+) + | ftsFieldGroupExplicitDisjunction (ftsFieldGroupExplicitDisjunction)* + -> ^(FIELD_DISJUNCTION ftsFieldGroupExplicitDisjunction+) + ; + +ftsFieldGroupExplicitDisjunction + : ftsFieldGroupExplictConjunction (OR ftsFieldGroupExplictConjunction)* + -> ^(FIELD_DISJUNCTION ftsFieldGroupExplictConjunction+) + ; + +ftsFieldGroupExplictConjunction + : ftsFieldGroupNot (AND ftsFieldGroupNot)* + -> ^(FIELD_CONJUNCTION ftsFieldGroupNot+) + ; + + +ftsFieldGroupNot : MINUS ftsFieldGroupTest + -> FIELD_NEGATION ftsFieldGroupTest + | ftsFieldGroupTest + -> ftsFieldGroupTest + ; + + +ftsFieldGroupTest + : ftsFieldGroupTerm + -> ^(FG_TERM ftsFieldGroupTerm) + | ftsFieldGroupExactTerm + -> ^(FG_EXACT_TERM ftsFieldGroupExactTerm) + | ftsFieldGroupPhrase + -> ^(FG_PHRASE ftsFieldGroupPhrase) + | ftsFieldGroupSynonym + -> ^(FG_SYNONYM ftsFieldGroupSynonym) + | ftsFieldGroupProximity + -> ^(FG_PROXIMITY ftsFieldGroupProximity) + | ftsFieldGroupRange + -> ^(FG_RANGE ftsFieldGroupRange) + | LPAREN ftsFieldGroupImplicitConjunctionOrDisjunction RPAREN + -> ftsFieldGroupImplicitConjunctionOrDisjunction + ; + +ftsFieldGroupTerm + : FTSWORD + ; + +ftsFieldGroupExactTerm + : PLUS ftsFieldGroupTerm + -> ftsFieldGroupTerm + ; + +ftsFieldGroupPhrase + : FTSPHRASE + ; + +ftsFieldGroupSynonym + : TILDA ftsFieldGroupTerm + -> ftsFieldGroupTerm + ; + +ftsFieldGroupProximity + : ftsFieldGroupTerm STAR ftsFieldGroupTerm + -> ftsFieldGroupTerm ftsFieldGroupTerm + ; + +ftsFieldGroupRange: ftsFieldGroupTerm DOTDOT ftsFieldGroupTerm + -> ftsFieldGroupTerm ftsFieldGroupTerm + ; + +columnReference + : ( qualifier=identifier DOT )? name=identifier + -> ^(COLUMN_REF $name $qualifier?) + ; + +identifier + : ID + ; + +OR : ('O'|'o')('R'|'r'); +AND : ('A'|'a')('N'|'n')('D'|'d'); +NOT : ('N'|'n')('O'|'o')('T'|'t'); +TILDA : '~' ; +LPAREN : '(' ; +RPAREN : ')' ; +PLUS : '+' ; +MINUS : '-' ; +COLON : ':' ; +STAR : '*' ; +DOTDOT : '..' ; +DOT : '.' ; + +FTSWORD : INWORD+; + +fragment +INWORD : '\u0041' .. '\u005A' + | '\u0061' .. '\u007A' + | '\u00C0' .. '\u00D6' + | '\u00D8' .. '\u00F6' + | '\u00F8' .. '\u00FF' + | '\u0100' .. '\u1FFF' + | '\u3040' .. '\u318F' + | '\u3300' .. '\u337F' + | '\u3400' .. '\u3D2D' + | '\u4E00' .. '\u9FFF' + | '\uF900' .. '\uFAFF' + | '\uAC00' .. '\uD7AF' + | '\u0030' .. '\u0039' + | '\u0660' .. '\u0669' + | '\u06F0' .. '\u06F9' + | '\u0966' .. '\u096F' + | '\u09E6' .. '\u09EF' + | '\u0A66' .. '\u0A6F' + | '\u0AE6' .. '\u0AEF' + | '\u0B66' .. '\u0B6F' + | '\u0BE7' .. '\u0BEF' + | '\u0C66' .. '\u0C6F' + | '\u0CE6' .. '\u0CEF' + | '\u0D66' .. '\u0D6F' + | '\u0E50' .. '\u0E59' + | '\u0ED0' .. '\u0ED9' + | '\u1040' .. '\u1049' + ; + +FTSPHRASE + : '"' (~'"' | '""')* '"' ; + +ID : ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'0'..'0'|'_'|'$'|'#')* ; + +WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; } ; diff --git a/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java b/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java index ef007ed2ed..16ebe35b82 100644 --- a/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java +++ b/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java @@ -149,6 +149,13 @@ public interface DictionaryService @NotAuditable Collection getAspects(QName model); + /** + * @param model the model to retrieve associations for + * @return the names of all associations defined within the specified model + */ + @NotAuditable + public Collection getAssociations(QName model); + /** * @param name the name of the aspect to retrieve * @return the aspect definition (or null, if it doesn't exist) @@ -231,7 +238,7 @@ public interface DictionaryService Collection getProperties(QName model, QName dataType); /** - * Get all poroperties for the specified model + * Get all properties for the specified model * * @param model * @return @@ -247,6 +254,14 @@ public interface DictionaryService @NotAuditable AssociationDefinition getAssociation(QName associationName); + /** + * Get all the association definitions + + * @return all the association qnames + */ + @NotAuditable + Collection getAllAssociations(); + // TODO: Behaviour definitions } diff --git a/source/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java b/source/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java index c1ffea7b44..a83f590009 100644 --- a/source/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java +++ b/source/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java @@ -26,6 +26,7 @@ package org.alfresco.service.cmr.dictionary; import java.util.List; +import org.alfresco.repo.dictionary.IndexTokenisationMode; import org.alfresco.service.namespace.QName; /** @@ -103,9 +104,9 @@ public interface PropertyDefinition public boolean isStoredInIndex(); /** - * @return true => tokenised when it is indexed (the stored value will not be tokenised) + * @return IndexTokenisationMode.TREU => tokenised when it is indexed (the stored value will not be tokenised) */ - public boolean isTokenisedInIndex(); + public IndexTokenisationMode getIndexTokenisationMode(); /** * All non atomic properties will be indexed at the same time.