From cf91e0afe08467ab3812ae61c757c60903eac56a Mon Sep 17 00:00:00 2001 From: dhrn <14145706+dhrn@users.noreply.github.com> Date: Tue, 23 Feb 2021 15:26:37 +0530 Subject: [PATCH] [REPO-5552] more filtering capablities for aspect/type api (#301) * * more filter implementation * * aspect test case added * * fixed coments and more test added * * comments fixed * * import and data fixed * * removed unnecessary filter --- .../java/org/alfresco/rest/api/Aspects.java | 16 +- .../java/org/alfresco/rest/api/Types.java | 18 +- .../api/aspects/AspectEntityResource.java | 2 +- .../rest/api/impl/AbstractClassImpl.java | 225 ++++++++++- .../alfresco/rest/api/impl/AspectsImpl.java | 57 ++- .../org/alfresco/rest/api/impl/TypesImpl.java | 57 ++- .../rest/api/model/AbstractClass.java | 76 +++- .../org/alfresco/rest/api/model/Aspect.java | 11 +- .../alfresco/rest/api/model/Association.java | 158 ++++++++ .../rest/api/model/AssociationSource.java | 129 +++++++ .../org/alfresco/rest/api/model/Type.java | 11 +- .../rest/api/tests/BaseModelApiTest.java | 205 +++++++++- .../alfresco/rest/api/tests/TestAspects.java | 170 ++++++++- .../alfresco/rest/api/tests/TestTypes.java | 174 ++++++++- .../rest/api/tests/client/data/Aspect.java | 97 ++++- .../rest/api/tests/client/data/Type.java | 97 ++++- .../test/resources/models/mycompany-model.xml | 2 + .../test/resources/models/test-api-model.xml | 358 ++++++++++++++++++ .../src/test/resources/models/test-scan.xml | 6 +- .../test/resources/rest-api-test-context.xml | 1 + 20 files changed, 1732 insertions(+), 138 deletions(-) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/model/Association.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/model/AssociationSource.java create mode 100644 remote-api/src/test/resources/models/test-api-model.xml diff --git a/remote-api/src/main/java/org/alfresco/rest/api/Aspects.java b/remote-api/src/main/java/org/alfresco/rest/api/Aspects.java index 53da61d772..292419f2bb 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/Aspects.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/Aspects.java @@ -30,8 +30,22 @@ import org.alfresco.rest.api.model.Aspect; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Parameters; +/** + * Aspect API + */ public interface Aspects { + /** + * Lists aspects + * @param params + * @return Collection of aspects + */ CollectionWithPagingInfo listAspects(Parameters params); - Aspect getAspectById(String aspectId); + + /** + * Gets an aspect by id + * @param aspectId + * @return an aspect + */ + Aspect getAspect(String aspectId); } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/Types.java b/remote-api/src/main/java/org/alfresco/rest/api/Types.java index 4b27ba2233..b608d923ef 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/Types.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/Types.java @@ -30,8 +30,24 @@ import org.alfresco.rest.api.model.Type; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Parameters; +/** + * Types API + */ public interface Types { + /** + * Lists types + * + * @param params + * @return Collection of types + */ CollectionWithPagingInfo listTypes(Parameters params); - Type getType(String aspectId); + + /** + * Gets a type by id + * + * @param typeId + * @return type + */ + Type getType(String typeId); } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/aspects/AspectEntityResource.java b/remote-api/src/main/java/org/alfresco/rest/api/aspects/AspectEntityResource.java index 89a664241c..be4f169fa0 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/aspects/AspectEntityResource.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/aspects/AspectEntityResource.java @@ -61,6 +61,6 @@ public class AspectEntityResource implements EntityResourceAction.ReadById { - static String PARAM_MODEL_IDS = "modelIds"; - static String PARAM_PARENT_IDS = "parentIds"; + static String PARAM_MODEL_IDS = "modelId"; + static String PARAM_PARENT_IDS = "parentId"; static String PARAM_NAMESPACE_URI = "namespaceUri"; + static String PARAM_INCLUDE_SUBASPECTS = "INCLUDESUBASPECTS"; + static String PARAM_INCLUDE_SUBTYPES = "INCLUDESUBTYPES"; + static String PARAM_INCLUDE_PROPERTIES = "properties"; + static String PARAM_INCLUDE_MANDATORY_ASPECTS = "mandatoryAspects"; + static String PARAM_INCLUDE_ASSOCIATIONS = "associations"; + static List ALL_PROPERTIES = ImmutableList.of(PARAM_INCLUDE_PROPERTIES, PARAM_INCLUDE_MANDATORY_ASPECTS, PARAM_INCLUDE_ASSOCIATIONS); + + private DictionaryService dictionaryService; + private NamespacePrefixResolver namespaceService; + private ClassDefinitionMapper classDefinitionMapper; + + AbstractClassImpl(DictionaryService dictionaryService, NamespacePrefixResolver namespaceService, ClassDefinitionMapper classDefinitionMapper) + { + this.dictionaryService = dictionaryService; + this.namespaceService = namespaceService; + this.classDefinitionMapper = classDefinitionMapper; + } public CollectionWithPagingInfo createPagedResult(List list, Paging paging) { @@ -95,7 +129,13 @@ public class AbstractClassImpl { { ClassQueryWalker propertyWalker = new ClassQueryWalker(); QueryHelper.walk(queryParameters, propertyWalker); - return new ModelApiFilter(propertyWalker.getModelIds(), propertyWalker.getParentIds(), propertyWalker.getMatchedPrefix(), propertyWalker.getNotMatchedPrefix()); + + return ModelApiFilter.builder() + .withModelId(propertyWalker.getModelIds()) + .withParentIds(propertyWalker.getParentIds()) + .withMatchPrefix(propertyWalker.getMatchedPrefix()) + .withNotMatchPrefix(propertyWalker.getNotMatchedPrefix()) + .build(); } return null; } @@ -108,13 +148,137 @@ public class AbstractClassImpl { } listParam.stream() - .filter(String::isEmpty) + .filter(StringUtils::isBlank) .findAny() .ifPresent(qName -> { throw new IllegalArgumentException(StringUtils.capitalize(paramName) + " cannot be empty (i.e. '')"); }); } + + protected Set> parseModelIds(Set modelIds, String apiSuffix) + { + return modelIds.stream().map(modelId -> + { + QName qName = null; + boolean filterIncludeSubClass = false; + + int idx = modelId.lastIndexOf(' '); + if (idx > 0) + { + String suffix = modelId.substring(idx); + if (suffix.equalsIgnoreCase(" " + apiSuffix)) + { + filterIncludeSubClass = true; + modelId = modelId.substring(0, idx); + } + } + + try + { + qName = QName.createQName(modelId, this.namespaceService); + } + catch (Exception ex) + { + throw new InvalidArgumentException(modelId + " isn't a valid QName. " + ex.getMessage()); + } + + if (qName == null) + throw new InvalidArgumentException(modelId + " isn't a valid QName. "); + + return new Pair<>(qName, filterIncludeSubClass); + }).collect(Collectors.toSet()); + } + + + public T constructFromFilters(T abstractClass, org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition, List includes) { + + if (includes != null && includes.contains(PARAM_INCLUDE_PROPERTIES)) + { + List properties = Collections.emptyList(); + ClassDefinition _classDefinition = this.classDefinitionMapper.fromDictionaryClassDefinition(classDefinition, dictionaryService); + if (_classDefinition.getProperties() != null) + { + properties = _classDefinition.getProperties(); + } + abstractClass.setProperties(properties); + } + + if (includes != null && includes.contains(PARAM_INCLUDE_ASSOCIATIONS)) + { + List associations = getAssociations(classDefinition.getAssociations()); + abstractClass.setAssociations(associations); + } + + if (includes != null && includes.contains(PARAM_INCLUDE_MANDATORY_ASPECTS)) + { + if (classDefinition.getDefaultAspectNames() != null) + { + List aspects = classDefinition.getDefaultAspectNames().stream().map(QName::toPrefixString).collect(Collectors.toList()); + abstractClass.setMandatoryAspects(aspects); + } + } + + abstractClass.setIsContainer(classDefinition.isContainer()); + abstractClass.setIsArchive(classDefinition.getArchive()); + abstractClass.setIncludedInSupertypeQuery(classDefinition.getIncludedInSuperTypeQuery()); + return abstractClass; + } + + List getAssociations(Map associationDefinitionMap) + { + Collection associationDefinitions = associationDefinitionMap.values(); + + if (associationDefinitions.size() == 0) + return Collections.emptyList(); + + List associations = new ArrayList(); + + for (AssociationDefinition definition : associationDefinitions) + { + Association association = new Association(); + + association.setId(definition.getName().toPrefixString()); + association.setTitle(definition.getTitle()); + association.setDescription(definition.getDescription()); + association.setIsChild(definition.isChild()); + association.setIsProtected(definition.isProtected()); + + AssociationSource source = new AssociationSource(); + + String sourceRole = definition.getSourceRoleName() != null ? definition.getSourceRoleName().toPrefixString() : null; + source.setRole(sourceRole); + + String sourceClass = definition.getSourceClass() != null ? definition.getSourceClass().getName().toPrefixString() : null; + source.setCls(sourceClass); + + source.setIsMany(definition.isSourceMany()); + source.setIsMandatory(definition.isSourceMandatory()); + + AssociationSource target = new AssociationSource(); + String targetRole = definition.getTargetRoleName() != null ? definition.getTargetRoleName().toPrefixString() : null; + target.setRole(targetRole); + + String targetClass = definition.getTargetClass() != null ? definition.getTargetClass().getName().toPrefixString() : null; + target.setCls(targetClass); + + target.setIsMany(definition.isTargetMany()); + target.setIsMandatory(definition.isTargetMandatory()); + target.setIsMandatoryEnforced(definition.isTargetMandatoryEnforced()); + + association.setSource(source); + association.setTarget(target); + associations.add(association); + } + + return associations; + } + + public static Predicate distinctByKey(Function keyExtractor) { + Map seen = new ConcurrentHashMap<>(); + return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; + } + public static class ClassQueryWalker extends MapBasedQueryWalker { private Set modelIds = null; @@ -187,12 +351,8 @@ public class AbstractClassImpl { private String matchedPrefix; private String notMatchedPrefix; - public ModelApiFilter(Set modelIds, Set parentIds, String matchedPrefix, String notMatchedPrefix) + public ModelApiFilter() { - this.modelIds = modelIds; - this.parentIds = parentIds; - this.matchedPrefix = matchedPrefix; - this.notMatchedPrefix = notMatchedPrefix; } public Set getModelIds() @@ -214,5 +374,52 @@ public class AbstractClassImpl { { return parentIds; } + + public static ModelApiFilterBuilder builder() + { + return new ModelApiFilterBuilder(); + } + + public static class ModelApiFilterBuilder + { + private Set modelIds; + private Set parentIds; + private String matchedPrefix; + private String notMatchedPrefix; + + public ModelApiFilterBuilder withModelId(Set modelIds) + { + this.modelIds = modelIds; + return this; + } + + public ModelApiFilterBuilder withParentIds(Set parentIds) + { + this.parentIds = parentIds; + return this; + } + + public ModelApiFilterBuilder withMatchPrefix(String matchedPrefix) + { + this.matchedPrefix = matchedPrefix; + return this; + } + + public ModelApiFilterBuilder withNotMatchPrefix(String notMatchedPrefix) + { + this.notMatchedPrefix = notMatchedPrefix; + return this; + } + + public ModelApiFilter build() + { + ModelApiFilter modelApiFilter = new ModelApiFilter(); + modelApiFilter.modelIds = modelIds; + modelApiFilter.parentIds = parentIds; + modelApiFilter.matchedPrefix = matchedPrefix; + modelApiFilter.notMatchedPrefix = notMatchedPrefix; + return modelApiFilter; + } + } } } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/AspectsImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/AspectsImpl.java index fec0a4057d..aa72c9131f 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/AspectsImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/AspectsImpl.java @@ -26,10 +26,10 @@ package org.alfresco.rest.api.impl; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.rest.api.Aspects; import org.alfresco.rest.api.ClassDefinitionMapper; import org.alfresco.rest.api.model.Aspect; -import org.alfresco.rest.api.model.PropertyDefinition; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; @@ -41,10 +41,12 @@ import org.alfresco.service.cmr.dictionary.ModelDefinition; import org.alfresco.service.namespace.NamespaceException; import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; import org.alfresco.util.PropertyCheck; -import java.util.List; import java.util.Collection; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -76,6 +78,10 @@ public class AspectsImpl extends AbstractClassImpl implements Aspects PropertyCheck.mandatory(this, "classDefinitionMapper", classDefinitionMapper); } + AspectsImpl(DictionaryService dictionaryService, NamespacePrefixResolver namespaceService, ClassDefinitionMapper classDefinitionMapper) + { + super(dictionaryService, namespaceService, classDefinitionMapper); + } @Override public CollectionWithPagingInfo listAspects(Parameters params) @@ -87,7 +93,8 @@ public class AspectsImpl extends AbstractClassImpl implements Aspects if (query != null && query.getModelIds() != null) { validateListParam(query.getModelIds(), PARAM_MODEL_IDS); - aspectList = query.getModelIds().parallelStream().map(this::getModelAspects).flatMap(Collection::parallelStream); + Set> modelsFilter = parseModelIds(query.getModelIds(), PARAM_INCLUDE_SUBASPECTS); + aspectList = modelsFilter.parallelStream().map(this::getModelAspects).flatMap(Collection::parallelStream); } else if (query != null && query.getParentIds() != null) { @@ -100,13 +107,14 @@ public class AspectsImpl extends AbstractClassImpl implements Aspects } List allAspects = aspectList.filter((qName) -> filterByNamespace(query, qName)) - .map((qName) -> this.convertToAspect(dictionaryService.getAspect(qName))) + .map((qName) -> this.convertToAspect(dictionaryService.getAspect(qName), params.getInclude())) + .filter(distinctByKey(Aspect::getId)) .collect(Collectors.toList()); return createPagedResult(allAspects, paging); } @Override - public Aspect getAspectById(String aspectId) + public Aspect getAspect(String aspectId) { if (aspectId == null) throw new InvalidArgumentException("Invalid parameter: unknown scheme specified"); @@ -125,32 +133,49 @@ public class AspectsImpl extends AbstractClassImpl implements Aspects if (aspectDefinition == null) throw new EntityNotFoundException(aspectId); - return this.convertToAspect(aspectDefinition); + return this.convertToAspect(aspectDefinition, ALL_PROPERTIES); } - public Aspect convertToAspect(AspectDefinition aspectDefinition) + public Aspect convertToAspect(AspectDefinition aspectDefinition, List includes) { - List properties = this.classDefinitionMapper.fromDictionaryClassDefinition(aspectDefinition, dictionaryService).getProperties(); - return new Aspect(aspectDefinition, dictionaryService, properties); + try + { + Aspect aspect = new Aspect(aspectDefinition, dictionaryService); + constructFromFilters(aspect, aspectDefinition, includes); + return aspect; + } + catch (Exception ex) + { + throw new AlfrescoRuntimeException("Failed to parse Aspect: " + aspectDefinition.getName() + " . " + ex.getMessage()); + } } - private Collection getModelAspects(String modelId) + private Collection getModelAspects(Pair model) { ModelDefinition modelDefinition = null; - if (modelId == null) - throw new InvalidArgumentException("modelId is null"); - try { - modelDefinition = this.dictionaryService.getModel(QName.createQName(modelId, this.namespaceService)); + modelDefinition = this.dictionaryService.getModel(model.getFirst()); } - catch (NamespaceException exception) + catch (Exception exception) { throw new InvalidArgumentException(exception.getMessage()); } - return this.dictionaryService.getAspects(modelDefinition.getName()); + if (modelDefinition == null) + throw new EntityNotFoundException("model"); + + Collection aspects = this.dictionaryService.getAspects(modelDefinition.getName()); + + if (!model.getSecond()) + return aspects; + + Stream children = aspects.stream() + .map(aspect -> this.dictionaryService.getSubAspects(aspect, false)) + .flatMap(Collection::parallelStream); + + return Stream.concat(aspects.parallelStream(), children).collect(Collectors.toList()); } private Collection getChildAspects(String aspectId) diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/TypesImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/TypesImpl.java index 03473dadc6..2e54c5a36a 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/TypesImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/TypesImpl.java @@ -26,10 +26,10 @@ package org.alfresco.rest.api.impl; -import org.alfresco.rest.api.Types; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.rest.api.ClassDefinitionMapper; +import org.alfresco.rest.api.Types; import org.alfresco.rest.api.model.Type; -import org.alfresco.rest.api.model.PropertyDefinition; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; @@ -41,10 +41,12 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.namespace.NamespaceException; import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; import org.alfresco.util.PropertyCheck; -import java.util.List; import java.util.Collection; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -76,6 +78,10 @@ public class TypesImpl extends AbstractClassImpl implements Types PropertyCheck.mandatory(this, "classDefinitionMapper", classDefinitionMapper); } + TypesImpl(DictionaryService dictionaryService, NamespacePrefixResolver namespaceService, ClassDefinitionMapper classDefinitionMapper) + { + super(dictionaryService, namespaceService, classDefinitionMapper); + } @Override public CollectionWithPagingInfo listTypes(Parameters params) @@ -87,7 +93,8 @@ public class TypesImpl extends AbstractClassImpl implements Types if (query != null && query.getModelIds() != null) { validateListParam(query.getModelIds(), PARAM_MODEL_IDS); - typeList = query.getModelIds().parallelStream().map(this::getModelTypes).flatMap(Collection::parallelStream); + Set> modelsFilter = parseModelIds(query.getModelIds(), PARAM_INCLUDE_SUBTYPES); + typeList = modelsFilter.parallelStream().map(this::getModelTypes).flatMap(Collection::parallelStream); } else if (query != null && query.getParentIds() != null) { @@ -100,7 +107,8 @@ public class TypesImpl extends AbstractClassImpl implements Types } List allTypes = typeList.filter((qName) -> filterByNamespace(query, qName)) - .map((qName) -> this.convertToType(dictionaryService.getType(qName))) + .map((qName) -> this.convertToType(dictionaryService.getType(qName), params.getInclude())) + .filter(distinctByKey(Type::getId)) .collect(Collectors.toList()); return createPagedResult(allTypes, paging); } @@ -125,32 +133,49 @@ public class TypesImpl extends AbstractClassImpl implements Types if (typeDefinition == null) throw new EntityNotFoundException(typeId); - return this.convertToType(typeDefinition); + return this.convertToType(typeDefinition, ALL_PROPERTIES); } - public Type convertToType(TypeDefinition typeDefinition) + public Type convertToType(TypeDefinition typeDefinition, List includes) { - List properties = this.classDefinitionMapper.fromDictionaryClassDefinition(typeDefinition, dictionaryService).getProperties(); - return new Type(typeDefinition, dictionaryService, properties); + try + { + Type type = new Type(typeDefinition, dictionaryService); + constructFromFilters(type, typeDefinition, includes); + return type; + } + catch (Exception ex) + { + throw new AlfrescoRuntimeException("Failed to parse Type: " + typeDefinition.getName() + " . " + ex.getMessage()); + } } - private Collection getModelTypes(String modelId) + private Collection getModelTypes(Pair model) { ModelDefinition modelDefinition = null; - if (modelId == null) - throw new InvalidArgumentException("modelId is null"); - try { - modelDefinition = this.dictionaryService.getModel(QName.createQName(modelId, this.namespaceService)); + modelDefinition = this.dictionaryService.getModel(model.getFirst()); } - catch (NamespaceException exception) + catch (Exception exception) { throw new InvalidArgumentException(exception.getMessage()); } - return this.dictionaryService.getTypes(modelDefinition.getName()); + if (modelDefinition == null) + throw new EntityNotFoundException("model"); + + Collection aspects = this.dictionaryService.getTypes(modelDefinition.getName()); + + if (!model.getSecond()) + return aspects; + + Stream children = aspects.parallelStream() + .map(aspect -> this.dictionaryService.getSubTypes(aspect, false)) + .flatMap(Collection::parallelStream); + + return Stream.concat(aspects.parallelStream(), children).collect(Collectors.toList()); } private Collection getChildTypes(String typeId) diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClass.java b/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClass.java index ff4baf8edb..5c16b8cc3b 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClass.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClass.java @@ -31,17 +31,21 @@ import org.alfresco.service.cmr.dictionary.NamespaceDefinition; import org.alfresco.service.cmr.i18n.MessageLookup; import org.alfresco.service.namespace.QName; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Objects; public abstract class AbstractClass extends ClassDefinition implements Comparable { - String id; - String title; - String description; - String parentId; - Model model; + protected String id; + protected String title; + protected String description; + protected String parentId; + protected Boolean isContainer = null; + protected Boolean isArchive = null; + protected Boolean includedInSupertypeQuery = null; + protected List mandatoryAspects = null; + protected List associations = null; + protected Model model; public String getId() { @@ -93,13 +97,54 @@ public abstract class AbstractClass extends ClassDefinition implements Comparabl this.model = model; } - List setList(List sourceList) + public Boolean getIsContainer() { - if (sourceList == null) - { - return Collections. emptyList(); - } - return new ArrayList<>(sourceList); + return isContainer; + } + + public void setIsContainer(Boolean isContainer) + { + this.isContainer = isContainer; + } + + public Boolean getIsArchive() + { + return isArchive; + } + + public void setIsArchive(Boolean isArchive) + { + this.isArchive = isArchive; + } + + public Boolean getIncludedInSupertypeQuery() + { + return includedInSupertypeQuery; + } + + public void setIncludedInSupertypeQuery(Boolean includedInSupertypeQuery) + { + this.includedInSupertypeQuery = includedInSupertypeQuery; + } + + public List getMandatoryAspects() + { + return mandatoryAspects; + } + + public void setMandatoryAspects(List mandatoryAspects) + { + this.mandatoryAspects = mandatoryAspects; + } + + public List getAssociations() + { + return associations; + } + + public void setAssociations(List associations) + { + this.associations = associations; } String getParentNameAsString(QName parentQName) @@ -131,10 +176,7 @@ public abstract class AbstractClass extends ClassDefinition implements Comparabl @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); - return result; + return Objects.hash(id, title, description, parentId, properties, isContainer, isArchive, includedInSupertypeQuery, mandatoryAspects, associations, model); } @Override diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/Aspect.java b/remote-api/src/main/java/org/alfresco/rest/api/model/Aspect.java index c7fabee629..99a48e8747 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/Aspect.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Aspect.java @@ -29,21 +29,18 @@ package org.alfresco.rest.api.model; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.i18n.MessageLookup; -import java.util.List; - public class Aspect extends AbstractClass { public Aspect() { } - public Aspect(AspectDefinition aspectDefinition, MessageLookup messageLookup, List properties) + public Aspect(AspectDefinition aspectDefinition, MessageLookup messageLookup) { this.id = aspectDefinition.getName().toPrefixString(); this.title = aspectDefinition.getTitle(messageLookup); this.description = aspectDefinition.getDescription(messageLookup); this.parentId = getParentNameAsString(aspectDefinition.getParentName()); - this.properties = setList(properties); this.model = getModelInfo(aspectDefinition, messageLookup); } @@ -56,6 +53,12 @@ public class Aspect extends AbstractClass .append(", description=").append(this.description) .append(", parentId=").append(parentId) .append(", properties=").append(properties) + .append(", mandatoryAspects=").append(mandatoryAspects) + .append(", isContainer=").append(isContainer) + .append(", isArchive=").append(isArchive) + .append(", associations=").append(associations) + .append(", model=").append(model) + .append(", includedInSupertypeQuery=").append(includedInSupertypeQuery) .append(']'); return builder.toString(); } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/Association.java b/remote-api/src/main/java/org/alfresco/rest/api/model/Association.java new file mode 100644 index 0000000000..835e13d429 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Association.java @@ -0,0 +1,158 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.rest.api.model; + +import java.util.Objects; + +public class Association +{ + private String id; + private String title; + private String description; + private Boolean isChild; + private Boolean isProtected; + private AssociationSource source = null; + private AssociationSource target = null; + + public Association() + { + } + + public Association(String id, String title, String description, Boolean isChild, Boolean isProtected, AssociationSource source, AssociationSource target) + { + this.id = id; + this.title = title; + this.description = description; + this.isChild = isChild; + this.isProtected = isProtected; + this.source = source; + this.target = target; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public Boolean getIsChild() + { + return isChild; + } + + public void setIsChild(Boolean isChild) + { + this.isChild = isChild; + } + + public Boolean getIsProtected() + { + return isProtected; + } + + public void setIsProtected(Boolean isProtected) + { + this.isProtected = isProtected; + } + + public AssociationSource getSource() + { + return source; + } + + public void setSource(AssociationSource source) + { + this.source = source; + } + + public AssociationSource getTarget() + { + return target; + } + + public void setTarget(AssociationSource target) + { + this.target = target; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Association other = (Association) obj; + return Objects.equals(id, other.getId()) && + Objects.equals(title, other.getTitle()) && + Objects.equals(description, other.getDescription()) && + Objects.equals(isChild, other.getIsChild()) && + Objects.equals(isProtected, other.getIsProtected()) && + Objects.equals(source, other.getSource()) && + Objects.equals(target, other.getTarget()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(512); + builder.append("Association [id=").append(this.id) + .append(", title=").append(this.title) + .append(", description=").append(this.description) + .append(", isChild=").append(isChild) + .append(", isProtected=").append(isProtected) + .append(", source=").append(source) + .append(", target=").append(target) + .append(']'); + return builder.toString(); + } +} \ No newline at end of file diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/AssociationSource.java b/remote-api/src/main/java/org/alfresco/rest/api/model/AssociationSource.java new file mode 100644 index 0000000000..10bff5b398 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/AssociationSource.java @@ -0,0 +1,129 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.rest.api.model; + +import java.util.Objects; + +public class AssociationSource { + private String role = null; + private String cls = null; + private Boolean isMany = null; + private Boolean isMandatory = null; + private Boolean isMandatoryEnforced = null; + + public AssociationSource() + { + } + + public AssociationSource(String role, String cls, Boolean isMany, Boolean isMandatory, Boolean isMandatoryEnforced) + { + this.role = role; + this.cls = cls; + this.isMany = isMany; + this.isMandatory = isMandatory; + this.isMandatoryEnforced = isMandatoryEnforced; + } + + public String getRole() + { + return role; + } + + public void setRole(String role) + { + this.role = role; + } + + public String getCls() + { + return cls; + } + + public void setCls(String cls) + { + this.cls = cls; + } + + public Boolean getIsMany() + { + return isMany; + } + + public void setIsMany(Boolean isMany) + { + this.isMany = isMany; + } + + public Boolean getIsMandatory() + { + return isMandatory; + } + + public void setIsMandatory(Boolean isMandatory) + { + this.isMandatory = isMandatory; + } + + public Boolean getIsMandatoryEnforced() + { + return isMandatoryEnforced; + } + + public void setIsMandatoryEnforced(Boolean isMandatoryEnforced) + { + this.isMandatoryEnforced = isMandatoryEnforced; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AssociationSource other = (AssociationSource) obj; + return Objects.equals(role, other.getRole()) && + Objects.equals(cls, other.getCls()) && + Objects.equals(isMany, other.getIsMany()) && + Objects.equals(isMandatory, other.getIsMandatory()) && + Objects.equals(isMandatoryEnforced, other.getIsMandatoryEnforced()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(512); + builder.append("AssociationSource [role=").append(this.role) + .append(", cls=").append(this.cls) + .append(", isMany=").append(this.isMany) + .append(", isMandatory=").append(isMandatory) + .append(", isMandatoryEnforced=").append(isMandatoryEnforced) + .append(']'); + return builder.toString(); + } +} \ No newline at end of file diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/Type.java b/remote-api/src/main/java/org/alfresco/rest/api/model/Type.java index 1e19a7e8da..f7fe715e68 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/Type.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Type.java @@ -29,21 +29,18 @@ package org.alfresco.rest.api.model; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.i18n.MessageLookup; -import java.util.List; - public class Type extends AbstractClass { public Type() { } - public Type(TypeDefinition typeDefinition, MessageLookup messageLookup, List properties) + public Type(TypeDefinition typeDefinition, MessageLookup messageLookup) { this.id = typeDefinition.getName().toPrefixString(); this.title = typeDefinition.getTitle(messageLookup); this.description = typeDefinition.getDescription(messageLookup); this.parentId = getParentNameAsString(typeDefinition.getParentName()); - this.properties = setList(properties); this.model = getModelInfo(typeDefinition, messageLookup); } @@ -56,6 +53,12 @@ public class Type extends AbstractClass .append(", description=").append(this.description) .append(", parentId=").append(parentId) .append(", properties=").append(properties) + .append(", mandatoryAspects=").append(mandatoryAspects) + .append(", isContainer=").append(isContainer) + .append(", isArchive=").append(isArchive) + .append(", associations=").append(associations) + .append(", model=").append(model) + .append(", includedInSupertypeQuery=").append(includedInSupertypeQuery) .append(']'); return builder.toString(); } diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseModelApiTest.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseModelApiTest.java index c57aab0efe..a5807c7ff2 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseModelApiTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseModelApiTest.java @@ -26,22 +26,33 @@ package org.alfresco.rest.api.tests; +import com.google.common.collect.ImmutableList; +import org.alfresco.rest.api.model.Association; +import org.alfresco.rest.api.model.AssociationSource; import org.alfresco.rest.api.model.Model; import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.alfresco.rest.api.tests.client.data.Aspect; +import org.alfresco.rest.api.tests.client.data.Type; import org.junit.Before; import java.util.HashMap; import java.util.Map; +import java.util.Collections; +import java.util.Arrays; +import java.util.List; public class BaseModelApiTest extends AbstractBaseApiTest { - PublicApiClient.ListResponse aspects = null; - org.alfresco.rest.api.tests.client.data.Aspect aspect = null, childAspect = null, smartFilter = null, rescanAspect = null; + PublicApiClient.ListResponse aspects = null; + Aspect aspect = null, childAspect = null, smartFilterAspect = null, + rescanAspect = null, testAspect = null, testAllAspect = null; + PublicApiClient.ListResponse types = null; + Type type = null, whitePaperType = null, docType = null, publishableType = null, apiBaseType = null, + apiFileType = null, apiFileDerivedType = null, apiForcedType = null, apiFileDerivedNoArchiveType = null, + apiFolderType = null, apiOverrideType = null, apiOverride2Type = null, apiOverride3Type = null, apiNamedPropConstraintType = null; - PublicApiClient.ListResponse types = null; - org.alfresco.rest.api.tests.client.data.Type type = null, whitePaperType = null, docType = null; - + List allTypes = null; PublicApiClient.Paging paging = getPaging(0, 10); Map otherParams = new HashMap<>(); @@ -63,25 +74,40 @@ public class BaseModelApiTest extends AbstractBaseApiTest scanModel.setNamespaceUri("http://www.test.com/model/account/1.0"); scanModel.setNamespacePrefix("test"); + testAspect = new org.alfresco.rest.api.tests.client.data.Aspect(); + testAspect.setId("mycompany:testAspect"); + testAspect.setTitle("Test Aspect"); + testAspect.setModel(myCompanyModel); + testAspect.setIsContainer(false); + testAspect.setIncludedInSupertypeQuery(true); + testAspect.setIsArchive(true); + childAspect = new org.alfresco.rest.api.tests.client.data.Aspect(); childAspect.setId("mycompany:childAspect"); childAspect.setTitle("Child Aspect"); childAspect.setDescription("Child Aspect Description"); childAspect.setParentId("smf:smartFolder"); childAspect.setModel(myCompanyModel); + childAspect.setIsContainer(false); + childAspect.setIncludedInSupertypeQuery(true); rescanAspect = new org.alfresco.rest.api.tests.client.data.Aspect(); rescanAspect.setId("test:rescan"); rescanAspect.setTitle("rescan"); rescanAspect.setDescription("Doc that required to scan "); rescanAspect.setModel(scanModel); + rescanAspect.setIsContainer(false); + rescanAspect.setIncludedInSupertypeQuery(true); - smartFilter = new org.alfresco.rest.api.tests.client.data.Aspect(); - smartFilter.setId("test:smartFilter"); - smartFilter.setTitle("Smart filter"); - smartFilter.setDescription("Smart Filter"); - smartFilter.setParentId("cm:auditable"); - smartFilter.setModel(scanModel); + smartFilterAspect = new org.alfresco.rest.api.tests.client.data.Aspect(); + smartFilterAspect.setId("test:smartFilter"); + smartFilterAspect.setTitle("Smart filter"); + smartFilterAspect.setDescription("Smart Filter"); + smartFilterAspect.setParentId("mycompany:testAspect"); + smartFilterAspect.setModel(scanModel); + smartFilterAspect.setIsContainer(false); + smartFilterAspect.setIsArchive(true); + smartFilterAspect.setIncludedInSupertypeQuery(true); whitePaperType = new org.alfresco.rest.api.tests.client.data.Type(); whitePaperType.setId("mycompany:whitepaper"); @@ -89,6 +115,9 @@ public class BaseModelApiTest extends AbstractBaseApiTest whitePaperType.setDescription("Whitepaper"); whitePaperType.setParentId("mycompany:doc"); whitePaperType.setModel(myCompanyModel); + whitePaperType.setIsContainer(false); + whitePaperType.setIsArchive(true); + whitePaperType.setIncludedInSupertypeQuery(true); docType = new org.alfresco.rest.api.tests.client.data.Type(); docType.setId("mycompany:doc"); @@ -96,6 +125,160 @@ public class BaseModelApiTest extends AbstractBaseApiTest docType.setDescription("Doc"); docType.setParentId("cm:content"); docType.setModel(myCompanyModel); + docType.setIsContainer(false); + docType.setIsArchive(true); + docType.setIncludedInSupertypeQuery(true); + + publishableType = new org.alfresco.rest.api.tests.client.data.Type(); + publishableType.setId("test:publishable"); + publishableType.setParentId("mycompany:doc"); + publishableType.setIsContainer(false); + publishableType.setIsArchive(true); + publishableType.setIncludedInSupertypeQuery(true); + + Model testModel = new Model(); + testModel.setAuthor("Administrator"); + testModel.setId("api:apiModel"); + testModel.setNamespaceUri("http://www.api.t2/model/1.0"); + testModel.setNamespacePrefix("test2"); + + Model apiModel = new Model(); + apiModel.setAuthor("Administrator"); + apiModel.setId("api:apiModel"); + apiModel.setNamespaceUri("http://www.api.t1/model/1.0"); + apiModel.setNamespacePrefix("api"); + + AssociationSource testAllAspectSource = new AssociationSource(null, "test2:aspect-all", true, true, null); + AssociationSource testAllAspectTarget = new AssociationSource(null, "api:referenceable", false, false, false); + Association testAllAspectAssociation = new Association("api:assoc-all", null, null, null, false, testAllAspectSource, testAllAspectTarget); + testAllAspect = new org.alfresco.rest.api.tests.client.data.Aspect(); + testAllAspect.setId("test2:aspect-all"); + testAllAspect.setTitle("Aspect derived from other namespace"); + testAllAspect.setIsArchive(false); + testAllAspect.setIncludedInSupertypeQuery(false); + testAllAspect.setIsContainer(false); + testAllAspect.setModel(testModel); + testAllAspect.setAssociations(Collections.singletonList(testAllAspectAssociation)); + testAllAspect.setMandatoryAspects(Arrays.asList("test2:aspect-three", "api:aspect-one", "api:aspect-two")); + + AssociationSource apiBaseSource = new AssociationSource(null, "api:base", false, true, null); + AssociationSource apiBaseTarget = new AssociationSource(null, "api:base", true, false, false); + Association apiBaseAssociation = new Association("api:assoc1", null, null, false, false, apiBaseSource, apiBaseTarget); + + AssociationSource apiChildSource = new AssociationSource(null, "api:base", true, true, null); + AssociationSource apiChildTarget = new AssociationSource(null, "api:referenceable", false, false, false); + Association apiChildAssociation = new Association("api:childassoc1", null, null, true, false, apiChildSource, apiChildTarget); + + AssociationSource apiBaseSource2 = new AssociationSource(null, "api:base", true, true, null); + AssociationSource apiBaseTarget2 = new AssociationSource(null, "api:referenceable", false, false, false); + Association apiBaseAssociation2 = new Association("api:assoc2", null, null, false, false, apiBaseSource2, apiBaseTarget2); + + AssociationSource apiChildPropagateSource = new AssociationSource(null, "api:base", true, true, null); + AssociationSource apiChildPropagateTarget = new AssociationSource(null, "api:referenceable", false, false, false); + Association apiChildPropagateAssociation = new Association("api:childassocPropagate", null, null, true, false, apiChildPropagateSource, apiChildPropagateTarget); + + apiBaseType = new org.alfresco.rest.api.tests.client.data.Type(); + apiBaseType.setId("api:base"); + apiBaseType.setTitle("Base"); + apiBaseType.setDescription("The Base Type"); + apiBaseType.setIncludedInSupertypeQuery(true); + apiBaseType.setIsContainer(true); + apiBaseType.setModel(apiModel); + apiBaseType.setAssociations(Arrays.asList(apiBaseAssociation, apiChildAssociation, apiBaseAssociation2, apiChildPropagateAssociation)); + apiBaseType.setMandatoryAspects(Collections.singletonList("api:referenceable")); + + apiForcedType = new org.alfresco.rest.api.tests.client.data.Type(); + apiForcedType.setId("api:enforced"); + apiForcedType.setParentId("api:base"); + apiForcedType.setIncludedInSupertypeQuery(true); + apiForcedType.setIsContainer(true); + apiForcedType.setModel(apiModel); + apiForcedType.setAssociations(Arrays.asList(apiBaseAssociation2, apiChildPropagateAssociation, apiBaseAssociation, apiChildAssociation)); + apiForcedType.setMandatoryAspects(Collections.singletonList("api:referenceable")); + + AssociationSource apiChildSource2 = new AssociationSource(null, "api:file", false, true, null); + AssociationSource apiChildTarget2 = new AssociationSource(null, "api:referenceable", true, false, false); + Association apiChildAssociation2 = new Association("api:childassoc2", null, null, true, false, apiChildSource2, apiChildTarget2); + apiFileType = new org.alfresco.rest.api.tests.client.data.Type(); + apiFileType.setId("api:file"); + apiFileType.setParentId("api:base"); + apiFileType.setIsArchive(true); + apiFileType.setIncludedInSupertypeQuery(true); + apiFileType.setIsContainer(true); + apiFileType.setModel(apiModel); + apiFileType.setAssociations(Arrays.asList(apiBaseAssociation2, apiChildAssociation2, apiChildPropagateAssociation, apiBaseAssociation, apiChildAssociation)); + apiFileType.setMandatoryAspects(Collections.singletonList("api:referenceable")); + + apiFileDerivedType = new org.alfresco.rest.api.tests.client.data.Type(); + apiFileDerivedType.setId("api:file-derived"); + apiFileDerivedType.setParentId("api:file"); + apiFileDerivedType.setIsArchive(true); + apiFileDerivedType.setIncludedInSupertypeQuery(true); + apiFileDerivedType.setIsContainer(true); + apiFileDerivedType.setModel(apiModel); + apiFileDerivedType.setAssociations(Arrays.asList(apiBaseAssociation2, apiChildAssociation2, apiChildPropagateAssociation, apiBaseAssociation, apiChildAssociation)); + apiFileDerivedType.setMandatoryAspects(Collections.singletonList("api:referenceable")); + + apiFileDerivedNoArchiveType = new org.alfresco.rest.api.tests.client.data.Type(); + apiFileDerivedNoArchiveType.setId("api:file-derived-no-archive"); + apiFileDerivedNoArchiveType.setParentId("api:file"); + apiFileDerivedNoArchiveType.setIsArchive(false); + apiFileDerivedNoArchiveType.setIncludedInSupertypeQuery(true); + apiFileDerivedNoArchiveType.setIsContainer(true); + apiFileDerivedNoArchiveType.setModel(apiModel); + apiFileDerivedNoArchiveType.setAssociations(Arrays.asList(apiBaseAssociation2, apiChildAssociation2, apiChildPropagateAssociation, apiBaseAssociation, apiChildAssociation)); + apiFileDerivedNoArchiveType.setMandatoryAspects(Collections.singletonList("api:referenceable")); + + apiFolderType = new org.alfresco.rest.api.tests.client.data.Type(); + apiFolderType.setId("api:folder"); + apiFolderType.setParentId("api:base"); + apiFolderType.setIncludedInSupertypeQuery(true); + apiFolderType.setIsContainer(true); + apiFolderType.setModel(apiModel); + apiFolderType.setAssociations(Arrays.asList(apiBaseAssociation2, apiChildPropagateAssociation, apiBaseAssociation, apiChildAssociation)); + apiFolderType.setMandatoryAspects(Collections.singletonList("api:referenceable")); + + apiOverrideType = new org.alfresco.rest.api.tests.client.data.Type(); + apiOverrideType.setId("api:overridetype1"); + apiOverrideType.setParentId("api:base"); + apiOverrideType.setIncludedInSupertypeQuery(true); + apiOverrideType.setIsContainer(false); + apiOverrideType.setModel(apiModel); + apiOverrideType.setAssociations(Collections.emptyList()); + apiOverrideType.setMandatoryAspects(Collections.emptyList()); + + apiOverride2Type = new org.alfresco.rest.api.tests.client.data.Type(); + apiOverride2Type.setId("api:overridetype2"); + apiOverride2Type.setParentId("api:overridetype1"); + apiOverride2Type.setIncludedInSupertypeQuery(true); + apiOverride2Type.setIsContainer(false); + apiOverride2Type.setModel(apiModel); + apiOverride2Type.setAssociations(Collections.emptyList()); + apiOverride2Type.setMandatoryAspects(Collections.emptyList()); + + apiOverride3Type = new org.alfresco.rest.api.tests.client.data.Type(); + apiOverride3Type.setId("api:overridetype3"); + apiOverride3Type.setParentId("api:overridetype2"); + apiOverride3Type.setIncludedInSupertypeQuery(true); + apiOverride3Type.setIsContainer(false); + apiOverride3Type.setModel(apiModel); + apiOverride3Type.setAssociations(Collections.emptyList()); + apiOverride3Type.setMandatoryAspects(Collections.emptyList()); + + apiNamedPropConstraintType = new org.alfresco.rest.api.tests.client.data.Type(); + apiNamedPropConstraintType.setId("api:typeWithNamedPropConstraint"); + apiNamedPropConstraintType.setTitle("Type with named property-defined constraint."); + apiNamedPropConstraintType.setDescription("A type with a named constraint defined within one of its properties."); + apiNamedPropConstraintType.setParentId("api:overridetype2"); + apiNamedPropConstraintType.setIncludedInSupertypeQuery(true); + apiNamedPropConstraintType.setIsContainer(false); + apiNamedPropConstraintType.setModel(apiModel); + apiNamedPropConstraintType.setAssociations(Collections.emptyList()); + apiNamedPropConstraintType.setMandatoryAspects(Collections.emptyList()); + + allTypes = ImmutableList.of(apiBaseType, apiForcedType, apiFileType, apiFileDerivedType, + apiFileDerivedNoArchiveType, apiFolderType, apiOverrideType, apiOverride2Type, + apiOverride3Type, apiNamedPropConstraintType); } @Override diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/TestAspects.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/TestAspects.java index e1be516873..64586f07f4 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/TestAspects.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/TestAspects.java @@ -29,12 +29,15 @@ package org.alfresco.rest.api.tests; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.rest.api.tests.client.PublicApiException; import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Aspect; import org.apache.commons.httpclient.HttpStatus; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; @@ -79,29 +82,32 @@ public class TestAspects extends BaseModelApiTest AuthenticationUtil.setRunAsUser(user1); publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); - otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable'))"); + otherParams.put("where", "(parentId in ('smf:smartFolder','mycompany:testAspect'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); - aspects.getList().get(1).expected(childAspect); + aspects.getList().get(0).expected(childAspect); + aspects.getList().get(1).expected(testAspect); + aspects.getList().get(3).expected(smartFilterAspect); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(4)); assertFalse(aspects.getPaging().getHasMoreItems()); - otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable') AND namespaceUri matches('http://www.test.*'))"); + otherParams.put("where", "(parentId in ('smf:smartFolder','mycompany:testAspect') AND namespaceUri matches('http://www.test.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); - aspects.getList().get(0).expected(smartFilter); + aspects.getList().get(0).expected(smartFilterAspect); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(1)); - otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable') AND not namespaceUri matches('http://www.test.*'))"); + otherParams.put("where", "(parentId in ('smf:smartFolder', 'mycompany:testAspect') AND not namespaceUri matches('http://www.test.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); - aspects.getList().get(1).expected(childAspect); + aspects.getList().get(0).expected(childAspect); + aspects.getList().get(1).expected(testAspect); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(3)); // match everything - otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable') AND namespaceUri matches('.*'))"); + otherParams.put("where", "(parentId in ('smf:smartFolder','mycompany:testAspect') AND namespaceUri matches('.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(4)); // match nothing - otherParams.put("where", "(parentIds in ('smf:smartFolder,cm:auditable') AND not namespaceUri matches('.*'))"); + otherParams.put("where", "(parentId in ('smf:smartFolder', 'mycompany:testAspect') AND not namespaceUri matches('.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(0)); } @@ -112,31 +118,148 @@ public class TestAspects extends BaseModelApiTest AuthenticationUtil.setRunAsUser(user1); publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(6)); assertFalse(aspects.getPaging().getHasMoreItems()); - - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.test.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.test.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); aspects.getList().get(0).expected(rescanAspect); - aspects.getList().get(1).expected(smartFilter); + aspects.getList().get(1).expected(smartFilterAspect); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(2)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND not namespaceUri matches('http://www.test.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND not namespaceUri matches('http://www.test.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(4)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND namespaceUri matches('.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(6)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND not namespaceUri matches('.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND not namespaceUri matches('.*'))"); aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(0)); } + @Test + public void testIncludeProperty() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.test.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(0).expected(rescanAspect); + assertNull(aspects.getList().get(0).getProperties()); + aspects.getList().get(1).expected(smartFilterAspect); + assertNull(aspects.getList().get(1).getProperties()); + + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.test.*'))"); + otherParams.put("include", "properties"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(0).expected(rescanAspect); + assertNotNull(aspects.getList().get(0).getProperties()); + aspects.getList().get(1).expected(smartFilterAspect); + assertNotNull(aspects.getList().get(0).getProperties()); + } + + @Test + public void testIncludeAssociation() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('api:apiModel'))"); + otherParams.put("include", "associations"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(6)); + + for (Aspect aspect : aspects.getList()) + { + assertNotNull(aspect.getAssociations()); + assertNull(aspect.getProperties()); + assertNull(aspect.getMandatoryAspects()); + } + assertTrue(aspects.getList().get(0).getAssociations().isEmpty()); + assertTrue(aspects.getList().get(1).getAssociations().isEmpty()); + assertTrue(aspects.getList().get(2).getAssociations().isEmpty()); + assertTrue(aspects.getList().get(3).getAssociations().isEmpty()); + assertEquals(aspects.getList().get(4).getAssociations(), testAllAspect.getAssociations()); + assertTrue(aspects.getList().get(5).getAssociations().isEmpty()); + } + + @Test + public void testIncludeMandatoryAspect() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('api:apiModel'))"); + otherParams.put("include", "mandatoryAspects"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(6)); + + for (Aspect aspect : aspects.getList()) + { + assertNotNull(aspect.getMandatoryAspects()); + assertNull(aspect.getProperties()); + assertNull(aspect.getAssociations()); + } + assertTrue(aspects.getList().get(0).getMandatoryAspects().isEmpty()); + assertTrue(aspects.getList().get(1).getMandatoryAspects().isEmpty()); + assertTrue(aspects.getList().get(2).getMandatoryAspects().isEmpty()); + assertTrue(aspects.getList().get(3).getMandatoryAspects().isEmpty()); + assertEquals(aspects.getList().get(4).getMandatoryAspects(), testAllAspect.getMandatoryAspects()); + assertTrue(aspects.getList().get(5).getMandatoryAspects().isEmpty()); + } + + @Test + public void testIncludes() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('api:apiModel'))"); + otherParams.put("include", "associations,mandatoryAspects"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(6)); + + for (Aspect aspect : aspects.getList()) + { + assertNotNull(aspect.getAssociations()); + assertNotNull(aspect.getMandatoryAspects()); + assertNull(aspect.getProperties()); + } + assertTrue(aspects.getList().get(0).getAssociations().isEmpty()); + assertTrue(aspects.getList().get(1).getAssociations().isEmpty()); + assertTrue(aspects.getList().get(2).getAssociations().isEmpty()); + assertTrue(aspects.getList().get(3).getAssociations().isEmpty()); + assertEquals(aspects.getList().get(4).getAssociations(), testAllAspect.getAssociations()); + assertEquals(aspects.getList().get(4).getMandatoryAspects(), testAllAspect.getMandatoryAspects()); + assertTrue(aspects.getList().get(5).getAssociations().isEmpty()); + } + + @Test + public void testSubAspects() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('mycompany:model'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(4)); + + otherParams.put("where", "(modelId in ('mycompany:model INCLUDESUBASPECTS'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(5)); + + otherParams.put("where", "(modelId in ('mycompany:model INCLUDESUBASPECTS') AND namespaceUri matches('http://www.test.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(0).expected(smartFilterAspect); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(1)); + } + @Test public void testAspectsById() throws PublicApiException { @@ -145,6 +268,11 @@ public class TestAspects extends BaseModelApiTest aspect = publicApiClient.aspects().getAspect("mycompany:childAspect"); aspect.expected(childAspect); + + aspect = publicApiClient.aspects().getAspect("test2:aspect-all"); + assertEquals("mandatoryAspects not matched", aspect.getMandatoryAspects(), testAllAspect.getMandatoryAspects()); + assertEquals("association not matched", aspect.getAssociations(), testAllAspect.getAssociations()); + aspect.expected(testAllAspect); } @Test @@ -153,12 +281,12 @@ public class TestAspects extends BaseModelApiTest AuthenticationUtil.setRunAsUser(user1); publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); - testListAspectException("(modelIds in ('mycompany:model','unknown:model','known:model'))"); - testListAspectException("(modelIds in ('unknown:model','mycompany:model'))"); - testListAspectException("(modelIds in (' ',' ',' ')"); - testListAspectException("(parentIds in ('smf:smartFolder','unknown:aspect'))"); - testListAspectException("(parentIds in ('unknown:aspect','smf:smartFolder'))"); - testListAspectException("(parentIds in (' ',' ',' ')"); + testListAspectException("(modelId in ('mycompany:model','unknown:model','known:model'))"); + testListAspectException("(modelId in ('unknown:model','mycompany:model'))"); + testListAspectException("(modelId in (' ',' ',' ')"); + testListAspectException("(parentId in ('smf:smartFolder','unknown:aspect'))"); + testListAspectException("(parentId in ('unknown:aspect','smf:smartFolder'))"); + testListAspectException("(parentId in (' ',' ',' ')"); testListAspectException("(namespaceUri matches('*'))"); // wrong pattern } diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/TestTypes.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/TestTypes.java index 210f50fc7d..1eae1a90d6 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/TestTypes.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/TestTypes.java @@ -29,12 +29,15 @@ package org.alfresco.rest.api.tests; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.rest.api.tests.client.PublicApiException; import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Type; import org.apache.commons.httpclient.HttpStatus; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; public class TestTypes extends BaseModelApiTest @@ -78,27 +81,27 @@ public class TestTypes extends BaseModelApiTest AuthenticationUtil.setRunAsUser(user1); publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); - otherParams.put("where", "(parentIds in ('cm:content'))"); + otherParams.put("where", "(parentId in ('cm:content'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); int total = types.getPaging().getTotalItems(); - otherParams.put("where", "(parentIds in ('cm:content') AND namespaceUri matches('http://www.mycompany.com/model.*'))"); + otherParams.put("where", "(parentId in ('cm:content') AND namespaceUri matches('http://www.mycompany.com/model.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); types.getList().get(0).expected(docType); types.getList().get(1).expected(whitePaperType); assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(2)); - otherParams.put("where", "(parentIds in ('cm:content') AND not namespaceUri matches('http://www.mycompany.com/model.*'))"); + otherParams.put("where", "(parentId in ('cm:content') AND not namespaceUri matches('http://www.mycompany.com/model.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(total - 2)); // match everything - otherParams.put("where", "(parentIds in ('cm:content') AND namespaceUri matches('.*'))"); + otherParams.put("where", "(parentId in ('cm:content') AND namespaceUri matches('.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(total)); // match nothing - otherParams.put("where", "(parentIds in ('cm:content') AND not namespaceUri matches('.*'))"); + otherParams.put("where", "(parentId in ('cm:content') AND not namespaceUri matches('.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(0)); } @@ -109,31 +112,156 @@ public class TestTypes extends BaseModelApiTest AuthenticationUtil.setRunAsUser(user1); publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); - assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(3)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(4)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.mycompany.com/model.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.mycompany.com/model.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); types.getList().get(0).expected(docType); types.getList().get(1).expected(whitePaperType); assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(2)); - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND not namespaceUri matches('http://www.mycompany.com/model.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND not namespaceUri matches('http://www.mycompany.com/model.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); - assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(1)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(2)); // match everything - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND namespaceUri matches('.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); - assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(3)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(4)); // match nothing - otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND not namespaceUri matches('.*'))"); + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND not namespaceUri matches('.*'))"); types = publicApiClient.types().getTypes(createParams(paging, otherParams)); assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(0)); } + @Test + public void testIncludeProperty() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('mycompany:model','test:scan'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(4)); + assertNull(types.getList().get(0).getProperties()); + assertNull(types.getList().get(1).getProperties()); + assertNull(types.getList().get(2).getProperties()); + + otherParams.put("where", "(modelId in ('mycompany:model','test:scan') AND namespaceUri matches('http://www.mycompany.com/model.*'))"); + otherParams.put("include", "properties"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + types.getList().get(0).expected(docType); + types.getList().get(1).expected(whitePaperType); + assertNotNull(types.getList().get(0).getProperties()); + assertNotNull(types.getList().get(1).getProperties()); + } + + @Test + public void testIncludeAssociation() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('api:apiModel'))"); + otherParams.put("include", "associations"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(10)); + + + for (int i = 0; i < types.getList().size(); i++) + { + Type type = types.getList().get(i); + + assertNotNull(type.getAssociations()); + assertNull(type.getProperties()); + assertNull(type.getMandatoryAspects()); + + type.expected(allTypes.get(i)); + assertEquals(type.getAssociations(), allTypes.get(i).getAssociations()); + } + } + + @Test + public void testIncludeMandatoryAspect() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('api:apiModel'))"); + otherParams.put("include", "mandatoryAspects"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + + for (int i = 0; i < types.getList().size(); i++) + { + Type type = types.getList().get(i); + + assertNotNull(type.getMandatoryAspects()); + assertNull(type.getProperties()); + assertNull(type.getAssociations()); + + type.expected(allTypes.get(i)); + assertEquals(type.getMandatoryAspects(), allTypes.get(i).getMandatoryAspects()); + } + } + + @Test + public void testIncludes() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('api:apiModel'))"); + otherParams.put("include", "associations,mandatoryAspects"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(10)); + + for (int i = 0; i < types.getList().size(); i++) + { + Type type = types.getList().get(i); + + assertNotNull(type.getAssociations()); + assertNull(type.getProperties()); + assertNotNull(type.getMandatoryAspects()); + + type.expected(allTypes.get(i)); + assertEquals(type.getMandatoryAspects(), allTypes.get(i).getMandatoryAspects()); + assertEquals(type.getAssociations(), allTypes.get(i).getAssociations()); + } + } + + @Test + public void testSubTypes() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelId in ('mycompany:model'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(2)); + types.getList().get(0).expected(docType); + types.getList().get(1).expected(whitePaperType); + + otherParams.put("where", "(modelId in ('mycompany:model INCLUDESUBTYPES'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(3)); + types.getList().get(0).expected(docType); + types.getList().get(1).expected(whitePaperType); + types.getList().get(2).expected(publishableType); + + otherParams.put("where", "(modelId in ('mycompany:model INCLUDESUBTYPES') AND namespaceUri matches('http://www.test.*'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(1)); + types.getList().get(0).expected(publishableType); + + otherParams.put("where", "(modelId in ('mycompany:model INCLUDESUBTYPES') AND not namespaceUri matches('http://www.test.*'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + types.getList().get(0).expected(docType); + types.getList().get(1).expected(whitePaperType); + } + @Test public void testTypesById() throws PublicApiException { @@ -142,6 +270,12 @@ public class TestTypes extends BaseModelApiTest type = publicApiClient.types().getType("mycompany:whitepaper"); type.expected(whitePaperType); + + type = publicApiClient.types().getType(apiBaseType.getId()); + type.expected(apiBaseType); + assertNotNull(type.getProperties()); + assertEquals(type.getMandatoryAspects(), apiBaseType.getMandatoryAspects()); + assertEquals(type.getAssociations(), apiBaseType.getAssociations()); } @Test @@ -150,13 +284,13 @@ public class TestTypes extends BaseModelApiTest AuthenticationUtil.setRunAsUser(user1); publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); - testListTypeException("(modelIds in ('mycompany:model','unknown:model'))"); - testListTypeException("(modelIds in ('unknown:model','unknown1:another'))"); - testListTypeException("(modelIds in (' ', '')"); - testListTypeException("(parentIds in ('cm:content','unknown:type')"); - testListTypeException("(parentIds in ('unknown:type','cm:content'))"); - testListTypeException("(parentIds in ('unknown:type','unknown:types'))"); - testListTypeException("(parentIds in (' ',' ',' '))"); + testListTypeException("(modelId in ('mycompany:model','unknown:model'))"); + testListTypeException("(modelId in ('unknown:model','unknown1:another'))"); + testListTypeException("(modelId in (' ', '')"); + testListTypeException("(parentId in ('cm:content','unknown:type')"); + testListTypeException("(parentId in ('unknown:type','cm:content'))"); + testListTypeException("(parentId in ('unknown:type','unknown:types'))"); + testListTypeException("(parentId in (' ',' ',' '))"); testListTypeException(""); testListTypeException("(namespaceUri matches('*'))"); // wrong pattern } diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Aspect.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Aspect.java index 276f62876e..aa9270c0f3 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Aspect.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Aspect.java @@ -25,6 +25,8 @@ */ package org.alfresco.rest.api.tests.client.data; +import org.alfresco.rest.api.model.Association; +import org.alfresco.rest.api.model.AssociationSource; import org.alfresco.rest.api.model.Model; import org.alfresco.rest.api.model.PropertyDefinition; import org.alfresco.rest.api.tests.client.PublicApiClient; @@ -52,6 +54,9 @@ public class Aspect extends org.alfresco.rest.api.model.Aspect implements Serial AssertUtil.assertEquals("title", getTitle(), other.getTitle()); AssertUtil.assertEquals("description", getDescription(), other.getDescription()); AssertUtil.assertEquals("parenId", getParentId(), other.getParentId()); + AssertUtil.assertEquals("isArchive", getIsArchive(), other.getIsArchive()); + AssertUtil.assertEquals("isContainer", getIsContainer(), other.getIsContainer()); + AssertUtil.assertEquals("includedInSupertypeQuery", getIncludedInSupertypeQuery(), other.getIncludedInSupertypeQuery()); if (getModel() != null && other.getModel() != null) { @@ -93,6 +98,31 @@ public class Aspect extends org.alfresco.rest.api.model.Aspect implements Serial jsonObject.put("model", getModel()); } + if (getMandatoryAspects() != null) + { + jsonObject.put("mandatoryAspects", getMandatoryAspects()); + } + + if (getIsContainer() != null) + { + jsonObject.put("isContainer", getIsContainer()); + } + + if (getIsArchive() != null) + { + jsonObject.put("isArchive", getIsArchive()); + } + + if (getIncludedInSupertypeQuery() != null) + { + jsonObject.put("includedInSupertypeQuery", getIncludedInSupertypeQuery()); + } + + if (getAssociations() != null) + { + jsonObject.put("associations", getAssociations()); + } + return jsonObject; } @@ -104,6 +134,52 @@ public class Aspect extends org.alfresco.rest.api.model.Aspect implements Serial String description = (String) jsonObject.get("description"); String parentId = (String) jsonObject.get("parentId"); List properties = (List) jsonObject.get("properties"); + List mandatoryAspects = jsonObject.get("mandatoryAspects") != null ? new ArrayList((List)jsonObject.get("mandatoryAspects")) : null; + Boolean isContainer = (Boolean) jsonObject.get("isContainer"); + Boolean isArchive = (Boolean) jsonObject.get("isArchive"); + Boolean includedInSupertypeQuery = (Boolean) jsonObject.get("includedInSupertypeQuery"); + + List associations = null; + + if (jsonObject.get("associations") != null) + { + associations = new ArrayList<>(); + JSONArray jsonArray = (JSONArray) jsonObject.get("associations"); + for(int i = 0; i < jsonArray.size(); i++) + { + Association association = new Association(); + JSONObject object = (JSONObject) jsonArray.get(i); + association.setId((String) object.get("id")); + association.setTitle((String) object.get("title")); + association.setDescription((String) object.get("description")); + association.setIsChild((Boolean) object.get("child")); + association.setIsProtected((Boolean) object.get("isProtected")); + + JSONObject sourceModel = (JSONObject) object.get("source"); + if (sourceModel != null) + { + AssociationSource source = new AssociationSource(); + source.setCls((String) sourceModel.get("cls")); + source.setRole((String) sourceModel.get("role")); + source.setIsMandatory((Boolean) sourceModel.get("isMandatory")); + source.setIsMany((Boolean) sourceModel.get("isMany")); + source.setIsMandatoryEnforced((Boolean) sourceModel.get("isMandatoryEnforced")); + association.setSource(source); + } + + JSONObject targetModel = (JSONObject) object.get("target"); + { + AssociationSource target = new AssociationSource(); + target.setCls((String) targetModel.get("cls")); + target.setRole((String) targetModel.get("role")); + target.setIsMandatory((Boolean) targetModel.get("isMandatory")); + target.setIsMany((Boolean) targetModel.get("isMany")); + target.setIsMandatoryEnforced((Boolean) targetModel.get("isMandatoryEnforced")); + association.setTarget(target); + } + associations.add(association); + } + } JSONObject jsonModel = (JSONObject) jsonObject.get("model"); Model model = new Model(); @@ -113,15 +189,20 @@ public class Aspect extends org.alfresco.rest.api.model.Aspect implements Serial model.setNamespaceUri((String) jsonModel.get("namespaceUri")); model.setAuthor((String) jsonModel.get("author")); - Aspect action = new Aspect(); - action.setId(id); - action.setTitle(title); - action.setDescription(description); - action.setParentId(parentId); - action.setProperties(properties); - action.setModel(model); + Aspect aspect = new Aspect(); + aspect.setId(id); + aspect.setTitle(title); + aspect.setDescription(description); + aspect.setParentId(parentId); + aspect.setProperties(properties); + aspect.setMandatoryAspects(mandatoryAspects); + aspect.setIsContainer(isContainer); + aspect.setIsArchive(isArchive); + aspect.setIncludedInSupertypeQuery(includedInSupertypeQuery); + aspect.setAssociations(associations); + aspect.setModel(model); - return action; + return aspect; } @SuppressWarnings("unchecked") diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Type.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Type.java index 18fb929fd4..78877ca766 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Type.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Type.java @@ -25,6 +25,8 @@ */ package org.alfresco.rest.api.tests.client.data; +import org.alfresco.rest.api.model.Association; +import org.alfresco.rest.api.model.AssociationSource; import org.alfresco.rest.api.model.Model; import org.alfresco.rest.api.model.PropertyDefinition; import org.alfresco.rest.api.tests.client.PublicApiClient; @@ -52,6 +54,9 @@ public class Type extends org.alfresco.rest.api.model.Type implements Serializab AssertUtil.assertEquals("title", getTitle(), other.getTitle()); AssertUtil.assertEquals("description", getDescription(), other.getDescription()); AssertUtil.assertEquals("parenId", getParentId(), other.getParentId()); + AssertUtil.assertEquals("isArchive", getIsArchive(), other.getIsArchive()); + AssertUtil.assertEquals("isContainer", getIsContainer(), other.getIsContainer()); + AssertUtil.assertEquals("includedInSupertypeQuery", getIncludedInSupertypeQuery(), other.getIncludedInSupertypeQuery()); if (getModel() != null && other.getModel() != null) { @@ -93,6 +98,31 @@ public class Type extends org.alfresco.rest.api.model.Type implements Serializab jsonObject.put("model", getModel()); } + if (getMandatoryAspects() != null) + { + jsonObject.put("mandatoryAspects", getMandatoryAspects()); + } + + if (getIsContainer() != null) + { + jsonObject.put("isContainer", getIsContainer()); + } + + if (getIsArchive() != null) + { + jsonObject.put("isArchive", getIsArchive()); + } + + if (getIncludedInSupertypeQuery() != null) + { + jsonObject.put("includedInSupertypeQuery", getIncludedInSupertypeQuery()); + } + + if (getAssociations() != null) + { + jsonObject.put("associations", getAssociations()); + } + return jsonObject; } @@ -104,6 +134,52 @@ public class Type extends org.alfresco.rest.api.model.Type implements Serializab String description = (String) jsonObject.get("description"); String parentId = (String) jsonObject.get("parentId"); List properties = (List) jsonObject.get("properties"); + List mandatoryAspects = jsonObject.get("mandatoryAspects") != null ? new ArrayList((List)jsonObject.get("mandatoryAspects")) : null; + Boolean isContainer = (Boolean) jsonObject.get("isContainer"); + Boolean isArchive = (Boolean) jsonObject.get("isArchive"); + Boolean includedInSupertypeQuery = (Boolean) jsonObject.get("includedInSupertypeQuery"); + + List associations = null; + + if (jsonObject.get("associations") != null) + { + associations = new ArrayList<>(); + JSONArray jsonArray = (JSONArray) jsonObject.get("associations"); + for(int i = 0; i < jsonArray.size(); i++) + { + org.alfresco.rest.api.model.Association association = new Association(); + JSONObject object = (JSONObject) jsonArray.get(i); + association.setId((String) object.get("id")); + association.setTitle((String) object.get("title")); + association.setDescription((String) object.get("description")); + association.setIsChild((Boolean) object.get("isChild")); + association.setIsProtected((Boolean) object.get("isProtected")); + + JSONObject sourceModel = (JSONObject) object.get("source"); + if (sourceModel != null) + { + AssociationSource source = new AssociationSource(); + source.setCls((String) sourceModel.get("cls")); + source.setRole((String) sourceModel.get("role")); + source.setIsMandatory((Boolean) sourceModel.get("isMandatory")); + source.setIsMany((Boolean) sourceModel.get("isMany")); + source.setIsMandatoryEnforced((Boolean) sourceModel.get("isMandatoryEnforced")); + association.setSource(source); + } + + JSONObject targetModel = (JSONObject) object.get("target"); + { + AssociationSource target = new AssociationSource(); + target.setCls((String) targetModel.get("cls")); + target.setRole((String) targetModel.get("role")); + target.setIsMandatory((Boolean) targetModel.get("isMandatory")); + target.setIsMany((Boolean) targetModel.get("isMany")); + target.setIsMandatoryEnforced((Boolean) targetModel.get("isMandatoryEnforced")); + association.setTarget(target); + } + associations.add(association); + } + } JSONObject jsonModel = (JSONObject) jsonObject.get("model"); Model model = new Model(); @@ -113,15 +189,20 @@ public class Type extends org.alfresco.rest.api.model.Type implements Serializab model.setNamespaceUri((String) jsonModel.get("namespaceUri")); model.setAuthor((String) jsonModel.get("author")); - Type action = new Type(); - action.setId(id); - action.setTitle(title); - action.setDescription(description); - action.setParentId(parentId); - action.setProperties(properties); - action.setModel(model); + Type type = new Type(); + type.setId(id); + type.setTitle(title); + type.setDescription(description); + type.setParentId(parentId); + type.setProperties(properties); + type.setMandatoryAspects(mandatoryAspects); + type.setIsContainer(isContainer); + type.setIsArchive(isArchive); + type.setIncludedInSupertypeQuery(includedInSupertypeQuery); + type.setAssociations(associations); + type.setModel(model); - return action; + return type; } @SuppressWarnings("unchecked") diff --git a/remote-api/src/test/resources/models/mycompany-model.xml b/remote-api/src/test/resources/models/mycompany-model.xml index 793e4082f2..4743091bfa 100644 --- a/remote-api/src/test/resources/models/mycompany-model.xml +++ b/remote-api/src/test/resources/models/mycompany-model.xml @@ -97,6 +97,8 @@ + Test Aspect + true Test Property diff --git a/remote-api/src/test/resources/models/test-api-model.xml b/remote-api/src/test/resources/models/test-api-model.xml new file mode 100644 index 0000000000..e563a973e7 --- /dev/null +++ b/remote-api/src/test/resources/models/test-api-model.xml @@ -0,0 +1,358 @@ + + Administrator + + + + + + + + + + + + + Regex1 title + Regex1 description + [A-Z]* + false + + + [a-z]* + false + + + 0 + 256 + + + 0 + 128 + + + 0 + 256 + + + List1 title + List1 description + + + ABC + DEF + VALUE WITH SPACES + VALUE WITH TRAILING SPACE + + + true + + + + + HIJ + + + true + + + + + XYZ + + + true + + + + + + Base + The Base Type + + + d:text + true + + + + + Prop1 Strlen1 title + Prop1 Strlen1 description + + + + + + + + true + false + + + api:base + false + true + + + + + true + true + + + api:referenceable + false + false + + + + + true + true + + + api:referenceable + false + false + + fred + true + + + + true + true + + + api:referenceable + false + false + + fred + true + true + + + + + api:referenceable + + + + + api:base + true + + + + d:text + true + + + + + + + + + api:referenceable + + fred + true + + + + + + an overriden default value + + + + + + + + + + api:file + + + + api:file + false + + + + api:base + + + d:text + true + + + + + + + api:base + + + d:text + true + + + d:text + true + + + d:text + true + + + + + + + + d:text + one + + + + + + api:overridetype1 + + + two + + + + + + api:overridetype2 + + + three + + + + + + Type with named property-defined constraint. + A type with a named constraint defined within one of its properties. + + + + + d:text + true + + + + Inline constraint + An inline constraint + + + ALPHA + BETA + GAMMA, DELTA + OMEGA + + + true + + + + + + + + + + Referenceable + The referenceable aspect + + + + + d:int + true + true + + + + + + + + Aspect Base + + + + d:text + + + + + + + + Aspect One + api:aspect-base + + + + + + + + + + Aspect Two + api:aspect-base + + + + + + + + + + + Aspect derived from other namespace + api:aspect-base + + + + + + + + + + Aspect derived from other namespace + false + false + + + + true + true + + + api:referenceable + false + false + + + + + test2:aspect-three + api:aspect-two + api:aspect-one + + + + diff --git a/remote-api/src/test/resources/models/test-scan.xml b/remote-api/src/test/resources/models/test-scan.xml index 20d163e941..3db3affaa8 100644 --- a/remote-api/src/test/resources/models/test-scan.xml +++ b/remote-api/src/test/resources/models/test-scan.xml @@ -5,6 +5,7 @@ + @@ -49,6 +50,9 @@ + + mycompany:doc + @@ -74,7 +78,7 @@ Smart filter Smart Filter - cm:auditable + mycompany:testAspect diff --git a/remote-api/src/test/resources/rest-api-test-context.xml b/remote-api/src/test/resources/rest-api-test-context.xml index 293e169f48..6d927f9f77 100644 --- a/remote-api/src/test/resources/rest-api-test-context.xml +++ b/remote-api/src/test/resources/rest-api-test-context.xml @@ -18,6 +18,7 @@ models/people-api.xml models/mycompany-model.xml models/test-scan.xml + models/test-api-model.xml