From 0211392ff6293233e12cfb7804bbb3bab82e2a8c Mon Sep 17 00:00:00 2001 From: dhrn <14145706+dhrn@users.noreply.github.com> Date: Fri, 5 Feb 2021 15:25:22 +0530 Subject: [PATCH] Aspect and Type api implementation (#261) * initial commit * * added match filters * api completed * * removed unwanted changes * fixed test * * fix consistant naming of class * fixed comments * * fixed comments * * aspects fixed * * types added * * fixed tes and minor improvemment * * fixed comments --- .../java/org/alfresco/rest/api/Aspects.java | 37 +++ ...Mapper.java => ClassDefinitionMapper.java} | 7 +- .../java/org/alfresco/rest/api/Types.java | 37 +++ .../api/aspects/AspectEntityResource.java | 66 +++++ .../rest/api/aspects/package-info.java | 30 +++ .../rest/api/impl/AbstractClassImpl.java | 218 ++++++++++++++++ .../alfresco/rest/api/impl/AspectsImpl.java | 171 ++++++++++++ ...pl.java => ClassDefinitionMapperImpl.java} | 50 ++-- .../rest/api/impl/CustomModelsImpl.java | 70 ++--- .../org/alfresco/rest/api/impl/NodesImpl.java | 14 +- .../org/alfresco/rest/api/impl/TypesImpl.java | 171 ++++++++++++ .../rest/api/model/AbstractClass.java | 124 +++++++++ ...assModel.java => AbstractCustomClass.java} | 52 ++-- .../org/alfresco/rest/api/model/Aspect.java | 62 +++++ ...deDefinition.java => ClassDefinition.java} | 8 +- ...straint.java => ConstraintDefinition.java} | 2 +- .../alfresco/rest/api/model/CustomAspect.java | 52 ++-- .../alfresco/rest/api/model/CustomType.java | 52 ++-- .../org/alfresco/rest/api/model/Node.java | 6 +- ...nProperty.java => PropertyDefinition.java} | 8 +- .../org/alfresco/rest/api/model/Type.java | 62 +++++ .../rest/api/types/TypeEntityResource.java | 66 +++++ .../alfresco/rest/api/types/package-info.java | 30 +++ .../alfresco/public-rest-context.xml | 54 +++- .../api/tests/BaseCustomModelApiTest.java | 10 +- .../alfresco/rest/api/tests/NodeApiTest.java | 40 +-- .../alfresco/rest/api/tests/TestAspects.java | 244 ++++++++++++++++++ .../alfresco/rest/api/tests/TestTypes.java | 238 +++++++++++++++++ .../api/tests/client/PublicApiClient.java | 49 +++- .../rest/api/tests/client/data/Aspect.java | 126 +++++++++ .../rest/api/tests/client/data/Node.java | 8 +- .../rest/api/tests/client/data/Type.java | 126 +++++++++ .../test/resources/models/mycompany-model.xml | 147 +++++++++++ .../src/test/resources/models/test-scan.xml | 84 ++++++ .../test/resources/rest-api-test-context.xml | 2 + 35 files changed, 2325 insertions(+), 198 deletions(-) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/Aspects.java rename remote-api/src/main/java/org/alfresco/rest/api/{NodeDefinitionMapper.java => ClassDefinitionMapper.java} (82%) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/Types.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/aspects/AspectEntityResource.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/aspects/package-info.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/impl/AbstractClassImpl.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/impl/AspectsImpl.java rename remote-api/src/main/java/org/alfresco/rest/api/impl/{NodeDefinitionMapperImpl.java => ClassDefinitionMapperImpl.java} (65%) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/impl/TypesImpl.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClass.java rename remote-api/src/main/java/org/alfresco/rest/api/model/{AbstractClassModel.java => AbstractCustomClass.java} (91%) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/model/Aspect.java rename remote-api/src/main/java/org/alfresco/rest/api/model/{NodeDefinition.java => ClassDefinition.java} (86%) rename remote-api/src/main/java/org/alfresco/rest/api/model/{NodeDefinitionConstraint.java => ConstraintDefinition.java} (98%) rename remote-api/src/main/java/org/alfresco/rest/api/model/{NodeDefinitionProperty.java => PropertyDefinition.java} (93%) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/model/Type.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/types/TypeEntityResource.java create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/types/package-info.java create mode 100644 remote-api/src/test/java/org/alfresco/rest/api/tests/TestAspects.java create mode 100644 remote-api/src/test/java/org/alfresco/rest/api/tests/TestTypes.java create mode 100644 remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Aspect.java create mode 100644 remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Type.java create mode 100644 remote-api/src/test/resources/models/mycompany-model.xml create mode 100644 remote-api/src/test/resources/models/test-scan.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 new file mode 100644 index 0000000000..53da61d772 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/Aspects.java @@ -0,0 +1,37 @@ +/* + * #%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; + +import org.alfresco.rest.api.model.Aspect; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; + +public interface Aspects +{ + CollectionWithPagingInfo listAspects(Parameters params); + Aspect getAspectById(String aspectId); +} diff --git a/remote-api/src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java b/remote-api/src/main/java/org/alfresco/rest/api/ClassDefinitionMapper.java similarity index 82% rename from remote-api/src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java rename to remote-api/src/main/java/org/alfresco/rest/api/ClassDefinitionMapper.java index 918be2531d..787f1d6b0f 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/ClassDefinitionMapper.java @@ -25,15 +25,14 @@ */ package org.alfresco.rest.api; -import org.alfresco.rest.api.model.NodeDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.i18n.MessageLookup; + /** * Maps representations from TypeDefinition to NodeDefinition * * @author gfertuso */ -public interface NodeDefinitionMapper +public interface ClassDefinitionMapper { - NodeDefinition fromTypeDefinition(TypeDefinition typeDefinition, MessageLookup messageLookup); + org.alfresco.rest.api.model.ClassDefinition fromDictionaryClassDefinition(org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition, MessageLookup messageLookup); } 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 new file mode 100644 index 0000000000..4b27ba2233 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/Types.java @@ -0,0 +1,37 @@ +/* + * #%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; + +import org.alfresco.rest.api.model.Type; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; + +public interface Types +{ + CollectionWithPagingInfo listTypes(Parameters params); + Type getType(String aspectId); +} 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 new file mode 100644 index 0000000000..89a664241c --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/aspects/AspectEntityResource.java @@ -0,0 +1,66 @@ +/* + * #%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.aspects; + +import org.alfresco.rest.api.Aspects; +import org.alfresco.rest.api.model.Aspect; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +@EntityResource(name = "aspects", title = "Aspects") +public class AspectEntityResource implements EntityResourceAction.ReadById, EntityResourceAction.Read, InitializingBean +{ + + private Aspects aspects; + + public void setAspects(Aspects aspects) + { + this.aspects = aspects; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("aspects", this.aspects); + } + + @Override + public CollectionWithPagingInfo readAll(Parameters params) + { + return aspects.listAspects(params); + } + + @Override + public Aspect readById(String id, Parameters parameters) + { + return aspects.getAspectById(id); + } +} diff --git a/remote-api/src/main/java/org/alfresco/rest/api/aspects/package-info.java b/remote-api/src/main/java/org/alfresco/rest/api/aspects/package-info.java new file mode 100644 index 0000000000..0cc3df5afe --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/aspects/package-info.java @@ -0,0 +1,30 @@ +/* + * #%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% + */ + +@WebApi(name="alfresco", scope= Api.SCOPE.PUBLIC, version=1) +package org.alfresco.rest.api.aspects; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.WebApi; \ No newline at end of file diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/AbstractClassImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/AbstractClassImpl.java new file mode 100644 index 0000000000..0868923121 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/AbstractClassImpl.java @@ -0,0 +1,218 @@ +/* + * #%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.impl; + +import org.alfresco.rest.api.model.AbstractClass; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.where.Query; +import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; +import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +public class AbstractClassImpl { + static String PARAM_MODEL_IDS = "modelIds"; + static String PARAM_PARENT_IDS = "parentIds"; + static String PARAM_NAMESPACE_URI = "namespaceUri"; + + public CollectionWithPagingInfo createPagedResult(List list, Paging paging) + { + int skipCount = paging.getSkipCount(); + int maxItems = paging.getMaxItems(); + int totalItems = list.size(); + + Collections.sort(list); + + if (skipCount >= totalItems) + { + List empty = Collections.emptyList(); + return CollectionWithPagingInfo.asPaged(paging, empty, false, totalItems); + } + else + { + int end = Math.min(skipCount + maxItems, totalItems); + boolean hasMoreItems = totalItems > end; + list = list.subList(skipCount, end); + return CollectionWithPagingInfo.asPaged(paging, list, hasMoreItems, totalItems); + } + } + + public boolean filterByNamespace(ModelApiFilter query, QName qName) + { + //System aspect/type is not allowed + if (qName.getNamespaceURI().equals(NamespaceService.SYSTEM_MODEL_1_0_URI)) + { + return false; + } + if (query != null && query.getMatchedPrefix() != null) + { + return Pattern.matches(query.getMatchedPrefix(), qName.getNamespaceURI()); + } + if (query != null && query.getNotMatchedPrefix() != null) + { + return !Pattern.matches(query.getNotMatchedPrefix(), qName.getNamespaceURI()); + } + return true; + } + + public ModelApiFilter getQuery(Query queryParameters) + { + if (queryParameters != null) + { + ClassQueryWalker propertyWalker = new ClassQueryWalker(); + QueryHelper.walk(queryParameters, propertyWalker); + return new ModelApiFilter(propertyWalker.getModelIds(), propertyWalker.getParentIds(), propertyWalker.getMatchedPrefix(), propertyWalker.getNotMatchedPrefix()); + } + return null; + } + + void validateListParam(Set listParam, String paramName) + { + if (listParam.isEmpty()) + { + throw new IllegalArgumentException(StringUtils.capitalize(paramName) + "s filter list cannot be empty."); + } + + listParam.stream() + .filter(String::isEmpty) + .findAny() + .ifPresent(qName -> { + throw new IllegalArgumentException(StringUtils.capitalize(paramName) + " cannot be empty (i.e. '')"); + }); + } + + public static class ClassQueryWalker extends MapBasedQueryWalker + { + private Set modelIds = null; + private Set parentIds = null; + private String notMatchedPrefix = null; + private String matchedPrefix = null; + + public ClassQueryWalker() + { + super(new HashSet<>(Arrays.asList(PARAM_MODEL_IDS, PARAM_PARENT_IDS)), new HashSet<>(Collections.singleton(PARAM_NAMESPACE_URI))); + } + + @Override + public void in(String propertyName, boolean negated, String... propertyValues) + { + if (negated) + { + throw new InvalidArgumentException("Cannot use NOT for " + propertyName); + } + + if (propertyName.equalsIgnoreCase(PARAM_MODEL_IDS)) + { + modelIds = new HashSet<>(Arrays.asList(propertyValues)); + } + + if (propertyName.equalsIgnoreCase(PARAM_PARENT_IDS)) + { + parentIds = new HashSet<>(Arrays.asList(propertyValues)); + } + } + + @Override + public void matches(String property, String value, boolean negated) + { + if (negated && property.equals(PARAM_NAMESPACE_URI)) + { + notMatchedPrefix = value; + } + else if (property.equals(PARAM_NAMESPACE_URI)) + { + matchedPrefix = value; + } + } + + public Set getModelIds() + { + return this.modelIds; + } + + public Set getParentIds() + { + return this.parentIds; + } + + public String getNotMatchedPrefix() + { + return this.notMatchedPrefix; + } + + public String getMatchedPrefix() + { + return this.matchedPrefix; + } + } + + public static class ModelApiFilter + { + private Set modelIds; + private Set parentIds; + private String matchedPrefix; + private String notMatchedPrefix; + + public ModelApiFilter(Set modelIds, Set parentIds, String matchedPrefix, String notMatchedPrefix) + { + this.modelIds = modelIds; + this.parentIds = parentIds; + this.matchedPrefix = matchedPrefix; + this.notMatchedPrefix = notMatchedPrefix; + } + + public Set getModelIds() + { + return modelIds; + } + + public String getMatchedPrefix() + { + return matchedPrefix; + } + + public String getNotMatchedPrefix() + { + return notMatchedPrefix; + } + + public Set getParentIds() + { + return parentIds; + } + } +} 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 new file mode 100644 index 0000000000..fec0a4057d --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/AspectsImpl.java @@ -0,0 +1,171 @@ +/* + * #%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.impl; + +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; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +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.PropertyCheck; + +import java.util.List; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class AspectsImpl extends AbstractClassImpl implements Aspects +{ + private DictionaryService dictionaryService; + private NamespacePrefixResolver namespaceService; + private ClassDefinitionMapper classDefinitionMapper; + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public void setNamespaceService(NamespacePrefixResolver namespaceService) + { + this.namespaceService = namespaceService; + } + + public void setClassDefinitionMapper(ClassDefinitionMapper classDefinitionMapper) + { + this.classDefinitionMapper = classDefinitionMapper; + } + + public void init() + { + PropertyCheck.mandatory(this, "dictionaryService", dictionaryService); + PropertyCheck.mandatory(this, "namespaceService", namespaceService); + PropertyCheck.mandatory(this, "classDefinitionMapper", classDefinitionMapper); + } + + + @Override + public CollectionWithPagingInfo listAspects(Parameters params) + { + Paging paging = params.getPaging(); + ModelApiFilter query = getQuery(params.getQuery()); + Stream aspectList = null; + + if (query != null && query.getModelIds() != null) + { + validateListParam(query.getModelIds(), PARAM_MODEL_IDS); + aspectList = query.getModelIds().parallelStream().map(this::getModelAspects).flatMap(Collection::parallelStream); + } + else if (query != null && query.getParentIds() != null) + { + validateListParam(query.getParentIds(), PARAM_PARENT_IDS); + aspectList = query.getParentIds().parallelStream().map(this::getChildAspects).flatMap(Collection::parallelStream); + } + else + { + aspectList = this.dictionaryService.getAllAspects().parallelStream(); + } + + List allAspects = aspectList.filter((qName) -> filterByNamespace(query, qName)) + .map((qName) -> this.convertToAspect(dictionaryService.getAspect(qName))) + .collect(Collectors.toList()); + return createPagedResult(allAspects, paging); + } + + @Override + public Aspect getAspectById(String aspectId) + { + if (aspectId == null) + throw new InvalidArgumentException("Invalid parameter: unknown scheme specified"); + + AspectDefinition aspectDefinition = null; + + try + { + aspectDefinition = dictionaryService.getAspect(QName.createQName(aspectId, this.namespaceService)); + } + catch (NamespaceException exception) + { + throw new EntityNotFoundException(aspectId); + } + + if (aspectDefinition == null) + throw new EntityNotFoundException(aspectId); + + return this.convertToAspect(aspectDefinition); + } + + public Aspect convertToAspect(AspectDefinition aspectDefinition) + { + List properties = this.classDefinitionMapper.fromDictionaryClassDefinition(aspectDefinition, dictionaryService).getProperties(); + return new Aspect(aspectDefinition, dictionaryService, properties); + } + + private Collection getModelAspects(String modelId) + { + ModelDefinition modelDefinition = null; + + if (modelId == null) + throw new InvalidArgumentException("modelId is null"); + + try + { + modelDefinition = this.dictionaryService.getModel(QName.createQName(modelId, this.namespaceService)); + } + catch (NamespaceException exception) + { + throw new InvalidArgumentException(exception.getMessage()); + } + + return this.dictionaryService.getAspects(modelDefinition.getName()); + } + + private Collection getChildAspects(String aspectId) + { + Collection subAspects = null; + try + { + QName parentAspect = QName.createQName(aspectId, this.namespaceService); + subAspects = this.dictionaryService.getSubAspects(parentAspect, true); + } + catch (NamespaceException exception) + { + throw new InvalidArgumentException(exception.getMessage()); + } + + return subAspects; + } +} \ No newline at end of file diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/ClassDefinitionMapperImpl.java similarity index 65% rename from remote-api/src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java rename to remote-api/src/main/java/org/alfresco/rest/api/impl/ClassDefinitionMapperImpl.java index edc477e126..b4d44a6394 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/ClassDefinitionMapperImpl.java @@ -32,13 +32,8 @@ import java.util.Map; import java.util.stream.Collectors; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; -import org.alfresco.rest.api.NodeDefinitionMapper; -import org.alfresco.rest.api.model.NodeDefinitionConstraint; -import org.alfresco.rest.api.model.NodeDefinition; -import org.alfresco.rest.api.model.NodeDefinitionProperty; -import org.alfresco.service.cmr.dictionary.ConstraintDefinition; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.rest.api.ClassDefinitionMapper; +import org.alfresco.rest.api.model.ClassDefinition; import org.alfresco.service.cmr.i18n.MessageLookup; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -47,33 +42,33 @@ import org.alfresco.service.namespace.QName; * * @author gfertuso */ -public class NodeDefinitionMapperImpl implements NodeDefinitionMapper +public class ClassDefinitionMapperImpl implements ClassDefinitionMapper { private final List EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI); private static final List EXCLUDED_PROPS = Arrays.asList(ContentModel.PROP_CONTENT); + @Override - public NodeDefinition fromTypeDefinition(TypeDefinition typeDefinition, - MessageLookup messageLookup) + public ClassDefinition fromDictionaryClassDefinition(org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition, MessageLookup messageLookup) { - - if (typeDefinition == null) + if (classDefinition == null) { - throw new AlfrescoRuntimeException("Undefined definition for the node"); + throw new AlfrescoRuntimeException("Undefined ClassDefinition for the node"); } - NodeDefinition nodeDefinition = new NodeDefinition(); - nodeDefinition.setProperties(getProperties(typeDefinition.getProperties(), messageLookup)); - - return nodeDefinition; + + ClassDefinition _classDefinition = new ClassDefinition(); + _classDefinition.setProperties(getProperties(classDefinition.getProperties(), messageLookup)); + + return _classDefinition; } - private boolean isPropertyExcluded(QName propertyName) + private boolean isPropertyExcluded(QName propertyName) { return EXCLUDED_NS.contains(propertyName.getNamespaceURI()) || EXCLUDED_PROPS.contains(propertyName); } - private List getProperties(Map propertiesMap, MessageLookup messageLookup) + private List getProperties(Map propertiesMap, MessageLookup messageLookup) { return propertiesMap.values().stream() .filter(p -> !isPropertyExcluded(p.getName())) @@ -81,10 +76,10 @@ public class NodeDefinitionMapperImpl implements NodeDefinitionMapper .collect(Collectors.toList()); } - private NodeDefinitionProperty fromPropertyDefinitionToProperty(PropertyDefinition propertyDefinition, - MessageLookup messageLookup) + private org.alfresco.rest.api.model.PropertyDefinition fromPropertyDefinitionToProperty(org.alfresco.service.cmr.dictionary.PropertyDefinition propertyDefinition, + MessageLookup messageLookup) { - NodeDefinitionProperty property = new NodeDefinitionProperty(); + org.alfresco.rest.api.model.PropertyDefinition property = new org.alfresco.rest.api.model.PropertyDefinition(); property.setId(propertyDefinition.getName().toPrefixString()); property.setTitle(propertyDefinition.getTitle(messageLookup)); property.setDescription(propertyDefinition.getDescription(messageLookup)); @@ -99,8 +94,8 @@ public class NodeDefinitionMapperImpl implements NodeDefinitionMapper return property; } - private List getConstraints( Collection constraintDefinitions, - MessageLookup messageLookup) + private List getConstraints(Collection constraintDefinitions, + MessageLookup messageLookup) { return constraintDefinitions.stream() @@ -109,10 +104,10 @@ public class NodeDefinitionMapperImpl implements NodeDefinitionMapper .collect(Collectors.toList()); } - private NodeDefinitionConstraint fromConstraintDefinitionToConstraint(ConstraintDefinition constraintDefinition, - MessageLookup messageLookup) + private org.alfresco.rest.api.model.ConstraintDefinition fromConstraintDefinitionToConstraint(org.alfresco.service.cmr.dictionary.ConstraintDefinition constraintDefinition, + MessageLookup messageLookup) { - NodeDefinitionConstraint constraint = new NodeDefinitionConstraint(); + org.alfresco.rest.api.model.ConstraintDefinition constraint = new org.alfresco.rest.api.model.ConstraintDefinition(); constraint.setId(constraintDefinition.getConstraint().getShortName()); constraint.setType(constraintDefinition.getConstraint().getType()); constraint.setTitle(constraintDefinition.getTitle(messageLookup)); @@ -120,5 +115,4 @@ public class NodeDefinitionMapperImpl implements NodeDefinitionMapper constraint.setParameters(constraintDefinition.getConstraint().getParameters()); return constraint; } - } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/CustomModelsImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/CustomModelsImpl.java index f1fa39df0d..78f24ace73 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/CustomModelsImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/CustomModelsImpl.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 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% - */ +/* + * #%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.impl; @@ -52,7 +52,7 @@ import org.alfresco.repo.dictionary.M2Type; import org.alfresco.repo.dictionary.ValueDataTypeValidator; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.rest.api.CustomModels; -import org.alfresco.rest.api.model.AbstractClassModel; +import org.alfresco.rest.api.model.AbstractCustomClass; import org.alfresco.rest.api.model.AbstractCommonDetails; import org.alfresco.rest.api.model.CustomAspect; import org.alfresco.rest.api.model.CustomModel; @@ -331,9 +331,9 @@ public class CustomModelsImpl implements CustomModels } } - private void replacePrefix(List existingTypesOrAspects, String modelOldNamespacePrefix, String modelNewNamespacePrefix) + private void replacePrefix(List existingTypesOrAspects, String modelOldNamespacePrefix, String modelNewNamespacePrefix) { - for(AbstractClassModel classModel : existingTypesOrAspects) + for(AbstractCustomClass classModel : existingTypesOrAspects) { // Type/Aspect's parent name String parentName = classModel.getParentName(); @@ -460,7 +460,7 @@ public class CustomModelsImpl implements CustomModels return updateTypeAspect(modelName, type, parameters); } - private T updateTypeAspect(String modelName, T classDef, Parameters parameters) + private T updateTypeAspect(String modelName, T classDef, Parameters parameters) { // Check the current user is authorised to update the custom model validateCurrentUser(); @@ -476,7 +476,7 @@ public class CustomModelsImpl implements CustomModels ModelDetails existingModelDetails = new ModelDetails(getCustomModelImpl(modelName)); - List allClassDefs = isAspect ? existingModelDetails.getAspects() : existingModelDetails.getTypes(); + List allClassDefs = isAspect ? existingModelDetails.getAspects() : existingModelDetails.getTypes(); @SuppressWarnings("unchecked") T existingClassDef = (T) getObjectByName(allClassDefs, name); @@ -1186,7 +1186,7 @@ public class CustomModelsImpl implements CustomModels m2Class.setParentName(parentPrefixedName); } - private void validateTypeAspectParent(AbstractClassModel typeAspect, CustomModel existingModel) + private void validateTypeAspectParent(AbstractCustomClass typeAspect, CustomModel existingModel) { String parentPrefixedName = typeAspect.getParentName(); if (StringUtils.isBlank(parentPrefixedName)) @@ -1305,7 +1305,7 @@ public class CustomModelsImpl implements CustomModels } } - private void mergeProperties(AbstractClassModel existingDetails, AbstractClassModel newDetails, Parameters parameters, boolean isModelActive) + private void mergeProperties(AbstractCustomClass existingDetails, AbstractCustomClass newDetails, Parameters parameters, boolean isModelActive) { validateList(newDetails.getProperties(), "cmm.rest_api.properties_empty_null"); @@ -1386,7 +1386,7 @@ public class CustomModelsImpl implements CustomModels } } - private void deleteProperty(AbstractClassModel existingClassModel, String propertyName) + private void deleteProperty(AbstractCustomClass existingClassModel, String propertyName) { // Transform existing properties into a map Map existingProperties = transformToMap(existingClassModel.getProperties(), toNameFunction()); @@ -1427,9 +1427,9 @@ public class CustomModelsImpl implements CustomModels return result; } - private void validateTypeAspectDelete(Collection list, String classPrefixedName) + private void validateTypeAspectDelete(Collection list, String classPrefixedName) { - for(AbstractClassModel acm : list) + for(AbstractCustomClass acm : list) { if(classPrefixedName.equals(acm.getParentName())) { diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java index 29b7280f50..ed8bb25a44 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -79,12 +79,12 @@ import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.virtual.store.VirtualStore; import org.alfresco.rest.antlr.WhereClauseParser; import org.alfresco.rest.api.Activities; -import org.alfresco.rest.api.NodeDefinitionMapper; +import org.alfresco.rest.api.ClassDefinitionMapper; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.QuickShareLinks; import org.alfresco.rest.api.model.AssocChild; import org.alfresco.rest.api.model.AssocTarget; -import org.alfresco.rest.api.model.NodeDefinition; +import org.alfresco.rest.api.model.ClassDefinition; import org.alfresco.rest.api.model.Document; import org.alfresco.rest.api.model.Folder; import org.alfresco.rest.api.model.LockInfo; @@ -214,7 +214,7 @@ public class NodesImpl implements Nodes private RetryingTransactionHelper retryingTransactionHelper; private LockService lockService; private VirtualStore smartStore; // note: remove as part of REPO-1173 - private NodeDefinitionMapper nodeDefinitionMapper; + private ClassDefinitionMapper classDefinitionMapper; private enum Activity_Type { @@ -328,9 +328,9 @@ public class NodesImpl implements Nodes this.smartStore = smartStore; } - public void setNodeDefinitionMapper(NodeDefinitionMapper nodeDefinitionMapper) + public void setClassDefinitionMapper(ClassDefinitionMapper classDefinitionMapper) { - this.nodeDefinitionMapper = nodeDefinitionMapper; + this.classDefinitionMapper = classDefinitionMapper; } // excluded namespaces (aspects, properties, assoc types) @@ -1041,8 +1041,8 @@ public class NodesImpl implements Nodes if (includeParam.contains(PARAM_INCLUDE_DEFINITION)) { - NodeDefinition nodeDefinition = nodeDefinitionMapper.fromTypeDefinition(getTypeDefinition(nodeRef), dictionaryService); - node.setDefinition(nodeDefinition); + ClassDefinition classDefinition = classDefinitionMapper.fromDictionaryClassDefinition(getTypeDefinition(nodeRef), dictionaryService); + node.setDefinition(classDefinition); } node.setNodeType(nodeTypeQName.toPrefixString(namespaceService)); 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 new file mode 100644 index 0000000000..03473dadc6 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/TypesImpl.java @@ -0,0 +1,171 @@ +/* + * #%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.impl; + +import org.alfresco.rest.api.Types; +import org.alfresco.rest.api.ClassDefinitionMapper; +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; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +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.PropertyCheck; + +import java.util.List; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class TypesImpl extends AbstractClassImpl implements Types +{ + private DictionaryService dictionaryService; + private NamespacePrefixResolver namespaceService; + private ClassDefinitionMapper classDefinitionMapper; + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public void setNamespaceService(NamespacePrefixResolver namespaceService) + { + this.namespaceService = namespaceService; + } + + public void setClassDefinitionMapper(ClassDefinitionMapper classDefinitionMapper) + { + this.classDefinitionMapper = classDefinitionMapper; + } + + public void init() + { + PropertyCheck.mandatory(this, "dictionaryService", dictionaryService); + PropertyCheck.mandatory(this, "namespaceService", namespaceService); + PropertyCheck.mandatory(this, "classDefinitionMapper", classDefinitionMapper); + } + + + @Override + public CollectionWithPagingInfo listTypes(Parameters params) + { + Paging paging = params.getPaging(); + ModelApiFilter query = getQuery(params.getQuery()); + Stream typeList = null; + + if (query != null && query.getModelIds() != null) + { + validateListParam(query.getModelIds(), PARAM_MODEL_IDS); + typeList = query.getModelIds().parallelStream().map(this::getModelTypes).flatMap(Collection::parallelStream); + } + else if (query != null && query.getParentIds() != null) + { + validateListParam(query.getParentIds(), PARAM_PARENT_IDS); + typeList = query.getParentIds().parallelStream().map(this::getChildTypes).flatMap(Collection::parallelStream); + } + else + { + typeList = this.dictionaryService.getAllTypes().parallelStream(); + } + + List allTypes = typeList.filter((qName) -> filterByNamespace(query, qName)) + .map((qName) -> this.convertToType(dictionaryService.getType(qName))) + .collect(Collectors.toList()); + return createPagedResult(allTypes, paging); + } + + @Override + public Type getType(String typeId) + { + if (typeId == null) + throw new InvalidArgumentException("Invalid parameter: unknown scheme specified"); + + TypeDefinition typeDefinition = null; + + try + { + typeDefinition = dictionaryService.getType(QName.createQName(typeId, this.namespaceService)); + } + catch (NamespaceException exception) + { + throw new EntityNotFoundException(typeId); + } + + if (typeDefinition == null) + throw new EntityNotFoundException(typeId); + + return this.convertToType(typeDefinition); + } + + public Type convertToType(TypeDefinition typeDefinition) + { + List properties = this.classDefinitionMapper.fromDictionaryClassDefinition(typeDefinition, dictionaryService).getProperties(); + return new Type(typeDefinition, dictionaryService, properties); + } + + private Collection getModelTypes(String modelId) + { + ModelDefinition modelDefinition = null; + + if (modelId == null) + throw new InvalidArgumentException("modelId is null"); + + try + { + modelDefinition = this.dictionaryService.getModel(QName.createQName(modelId, this.namespaceService)); + } + catch (NamespaceException exception) + { + throw new InvalidArgumentException(exception.getMessage()); + } + + return this.dictionaryService.getTypes(modelDefinition.getName()); + } + + private Collection getChildTypes(String typeId) + { + Collection subTypes = null; + try + { + QName parentType = QName.createQName(typeId, this.namespaceService); + subTypes = this.dictionaryService.getSubTypes(parentType, true); + } + catch (NamespaceException exception) + { + throw new InvalidArgumentException(exception.getMessage()); + } + + return subTypes; + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..cac150a299 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClass.java @@ -0,0 +1,124 @@ +/* + * #%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 org.alfresco.service.namespace.QName; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public abstract class AbstractClass extends ClassDefinition implements Comparable +{ + String id; + String title; + String description; + String parentId; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getTitle() + { + return this.title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return this.description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public String getParentId() + { + return parentId; + } + + public void setParentId(String parentId) + { + this.parentId = parentId; + } + + List setList(List sourceList) + { + if (sourceList == null) + { + return Collections. emptyList(); + } + return new ArrayList<>(sourceList); + } + + String getParentNameAsString(QName parentQName) + { + if (parentQName != null) + { + return parentQName.toPrefixString(); + } + return null; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + return super.equals(obj); + } + + @Override + public int compareTo(AbstractClass other) + { + return this.id.compareTo(other.getId()); + } +} diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClassModel.java b/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractCustomClass.java similarity index 91% rename from remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClassModel.java rename to remote-api/src/main/java/org/alfresco/rest/api/model/AbstractCustomClass.java index 9146ef9c30..28fc114375 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractClassModel.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/AbstractCustomClass.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 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% - */ +/* + * #%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; @@ -35,7 +35,7 @@ import org.alfresco.service.namespace.QName; /** * @author Jamal Kaabi-Mofrad */ -public abstract class AbstractClassModel extends AbstractCommonDetails +public abstract class AbstractCustomClass extends AbstractCommonDetails { /* package */String parentName; /* package */List properties = Collections.emptyList(); 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 new file mode 100644 index 0000000000..6bf9cf3494 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Aspect.java @@ -0,0 +1,62 @@ +/* + * #%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 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) + { + this.id = aspectDefinition.getName().toPrefixString(); + this.title = aspectDefinition.getTitle(messageLookup); + this.description = aspectDefinition.getDescription(messageLookup); + this.parentId = getParentNameAsString(aspectDefinition.getParentName()); + this.properties = setList(properties); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(512); + builder.append("Aspect [id=").append(this.id) + .append(", title=").append(this.title) + .append(", description=").append(this.description) + .append(", parentId=").append(parentId) + .append(", properties=").append(properties) + .append(']'); + return builder.toString(); + } +} + diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinition.java b/remote-api/src/main/java/org/alfresco/rest/api/model/ClassDefinition.java similarity index 86% rename from remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinition.java rename to remote-api/src/main/java/org/alfresco/rest/api/model/ClassDefinition.java index 227a150623..1fe5b80b08 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinition.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/ClassDefinition.java @@ -31,17 +31,17 @@ import java.util.List; * * @author gfertuso */ -public class NodeDefinition +public class ClassDefinition { - List properties; + List properties; - public List getProperties() + public List getProperties() { return properties; } - public void setProperties(List properties) + public void setProperties(List properties) { this.properties = properties; } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java b/remote-api/src/main/java/org/alfresco/rest/api/model/ConstraintDefinition.java similarity index 98% rename from remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java rename to remote-api/src/main/java/org/alfresco/rest/api/model/ConstraintDefinition.java index 8a7cbcb6fc..632605e871 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/ConstraintDefinition.java @@ -31,7 +31,7 @@ import java.util.Map; * * @author gfertuso */ -public class NodeDefinitionConstraint +public class ConstraintDefinition { private String id; private String type; diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/CustomAspect.java b/remote-api/src/main/java/org/alfresco/rest/api/model/CustomAspect.java index 6715f109d1..1e971495f9 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/CustomAspect.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/CustomAspect.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 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% - */ +/* + * #%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; @@ -34,7 +34,7 @@ import org.alfresco.service.cmr.i18n.MessageLookup; /** * @author Jamal Kaabi-Mofrad */ -public class CustomAspect extends AbstractClassModel +public class CustomAspect extends AbstractCustomClass { public CustomAspect() diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/CustomType.java b/remote-api/src/main/java/org/alfresco/rest/api/model/CustomType.java index bfaf5dc585..1865c12d3d 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/CustomType.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/CustomType.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 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% - */ +/* + * #%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; @@ -34,7 +34,7 @@ import org.alfresco.service.cmr.i18n.MessageLookup; /** * @author Jamal Kaabi-Mofrad */ -public class CustomType extends AbstractClassModel +public class CustomType extends AbstractCustomClass { public CustomType() diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/Node.java b/remote-api/src/main/java/org/alfresco/rest/api/model/Node.java index 9f3827d8f4..9c98efee6f 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/Node.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Node.java @@ -95,7 +95,7 @@ public class Node implements Comparable protected List allowableOperations; protected NodePermissions nodePermissions; - protected NodeDefinition definition; + protected ClassDefinition definition; //optional SearchEntry (only ever returned from a search) protected SearchEntry search = null; @@ -470,12 +470,12 @@ public class Node implements Comparable this.secondaryChildren = secondaryChildren; } - public NodeDefinition getDefinition() + public ClassDefinition getDefinition() { return definition; } - public void setDefinition(NodeDefinition definition) + public void setDefinition(ClassDefinition definition) { this.definition = definition; } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java b/remote-api/src/main/java/org/alfresco/rest/api/model/PropertyDefinition.java similarity index 93% rename from remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java rename to remote-api/src/main/java/org/alfresco/rest/api/model/PropertyDefinition.java index c07d02c066..10717e7778 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/PropertyDefinition.java @@ -31,7 +31,7 @@ import java.util.List; * * @author gfertuso */ -public class NodeDefinitionProperty +public class PropertyDefinition { private String id; private String title; @@ -42,7 +42,7 @@ public class NodeDefinitionProperty private Boolean isMandatory; private Boolean isMandatoryEnforced; private Boolean isProtected; - private List constraints; + private List constraints; public String getId() { @@ -104,12 +104,12 @@ public class NodeDefinitionProperty this.isProtected = isProtected; } - public List getConstraints() + public List getConstraints() { return constraints; } - public void setConstraints(List constraints) + public void setConstraints(List constraints) { this.constraints = constraints; } 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 new file mode 100644 index 0000000000..3eb8fdded6 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Type.java @@ -0,0 +1,62 @@ +/* + * #%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 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) + { + this.id = typeDefinition.getName().toPrefixString(); + this.title = typeDefinition.getTitle(messageLookup); + this.description = typeDefinition.getDescription(messageLookup); + this.parentId = getParentNameAsString(typeDefinition.getParentName()); + this.properties = setList(properties); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(512); + builder.append("Type [id=").append(this.id) + .append(", title=").append(this.title) + .append(", description=").append(this.description) + .append(", parentId=").append(parentId) + .append(", properties=").append(properties) + .append(']'); + return builder.toString(); + } +} + diff --git a/remote-api/src/main/java/org/alfresco/rest/api/types/TypeEntityResource.java b/remote-api/src/main/java/org/alfresco/rest/api/types/TypeEntityResource.java new file mode 100644 index 0000000000..1f8087cd44 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/types/TypeEntityResource.java @@ -0,0 +1,66 @@ +/* + * #%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.types; + +import org.alfresco.rest.api.Types; +import org.alfresco.rest.api.model.Type; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +@EntityResource(name = "types", title = "types") +public class TypeEntityResource implements EntityResourceAction.ReadById, EntityResourceAction.Read, InitializingBean +{ + + private Types types; + + public void setTypes(Types types) + { + this.types = types; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("types", this.types); + } + + @Override + public CollectionWithPagingInfo readAll(Parameters params) + { + return types.listTypes(params); + } + + @Override + public Type readById(String id, Parameters parameters) + { + return types.getType(id); + } +} diff --git a/remote-api/src/main/java/org/alfresco/rest/api/types/package-info.java b/remote-api/src/main/java/org/alfresco/rest/api/types/package-info.java new file mode 100644 index 0000000000..274cd64aa4 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/types/package-info.java @@ -0,0 +1,30 @@ +/* + * #%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% + */ + +@WebApi(name="alfresco", scope= Api.SCOPE.PUBLIC, version=1) +package org.alfresco.rest.api.types; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.WebApi; \ No newline at end of file diff --git a/remote-api/src/main/resources/alfresco/public-rest-context.xml b/remote-api/src/main/resources/alfresco/public-rest-context.xml index 4fc9af0e64..2d9a20b0f4 100644 --- a/remote-api/src/main/resources/alfresco/public-rest-context.xml +++ b/remote-api/src/main/resources/alfresco/public-rest-context.xml @@ -530,7 +530,7 @@ - + @@ -542,7 +542,7 @@ - + @@ -781,7 +781,7 @@ - + org.alfresco.rest.api.Sites @@ -1491,4 +1491,52 @@ + + + + + + + + + + + + + + org.alfresco.rest.api.Aspects + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.rest.api.Types + + + + + + + + + + diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseCustomModelApiTest.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseCustomModelApiTest.java index 18ad636b48..26a92db764 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseCustomModelApiTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/BaseCustomModelApiTest.java @@ -33,7 +33,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.rest.api.model.AbstractClassModel; +import org.alfresco.rest.api.model.AbstractCustomClass; import org.alfresco.rest.api.model.CustomAspect; import org.alfresco.rest.api.model.CustomModel; import org.alfresco.rest.api.model.CustomModel.ModelStatus; @@ -158,10 +158,10 @@ public class BaseCustomModelApiTest extends AbstractBaseApiTest return customModel; } - protected T createTypeAspect(Class glazz, String modelName, String typeAspectName, String title, String desc, - String parent) throws Exception + protected T createTypeAspect(Class glazz, String modelName, String typeAspectName, String title, String desc, + String parent) throws Exception { - AbstractClassModel classModel = null; + AbstractCustomClass classModel = null; String uri = "cmm/" + modelName; if (glazz.equals(CustomType.class)) { @@ -194,7 +194,7 @@ public class BaseCustomModelApiTest extends AbstractBaseApiTest assertTrue("Two models are not equal. Expected:<" + expectedModel.toString() + "> but was:<" + actualModel.toString() + ">", result); } - protected void compareCustomTypesAspects(AbstractClassModel expectedDetails, AbstractClassModel actualDetails, String... excludeFields) + protected void compareCustomTypesAspects(AbstractCustomClass expectedDetails, AbstractCustomClass actualDetails, String... excludeFields) { List expectedProps = expectedDetails.getProperties(); List actualProps = actualDetails.getProperties(); diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java index dde673be98..247a60df9b 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -62,11 +62,11 @@ import org.alfresco.repo.tenant.TenantUtil; import org.alfresco.rest.AbstractSingleNetworkSiteTest; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.model.LockInfo; -import org.alfresco.rest.api.model.NodeDefinition; -import org.alfresco.rest.api.model.NodeDefinitionConstraint; +import org.alfresco.rest.api.model.ClassDefinition; +import org.alfresco.rest.api.model.ConstraintDefinition; import org.alfresco.rest.api.model.NodePermissions; import org.alfresco.rest.api.model.NodeTarget; -import org.alfresco.rest.api.model.NodeDefinitionProperty; +import org.alfresco.rest.api.model.PropertyDefinition; import org.alfresco.rest.api.model.Site; import org.alfresco.rest.api.nodes.NodesEntityResource; import org.alfresco.rest.api.tests.client.HttpResponse; @@ -6173,19 +6173,19 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest params.put("include", "definition"); response = getSingle(NodesEntityResource.class, nodeId, params, 200); nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); - NodeDefinition nodeDefinition = nodeResp.getDefinition(); - assertNotNull(nodeDefinition); - checkDefinitionProperties(nodeDefinition.getProperties()); + ClassDefinition classDefinition = nodeResp.getDefinition(); + assertNotNull(classDefinition); + checkDefinitionProperties(classDefinition.getProperties()); } - private void checkDefinitionProperties(List properties) + private void checkDefinitionProperties(List properties) { assertNotNull(properties); shouldNotContainSystemProperties(properties); shouldContainParentProperties(properties); shouldContainAspectProperties(properties); - NodeDefinitionProperty testProperty = properties.stream(). + PropertyDefinition testProperty = properties.stream(). filter(property -> property.getId().equals("cm:name")) .findFirst() @@ -6202,7 +6202,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest } - private void shouldNotContainSystemProperties(List properties) + private void shouldNotContainSystemProperties(List properties) { assertTrue(properties.stream() .noneMatch(property -> @@ -6210,41 +6210,41 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest property.getId().equals(ContentModel.PROP_CONTENT.toPrefixString(namespaceService)))); } - private void shouldContainParentProperties(List properties) + private void shouldContainParentProperties(List properties) { assertTrue(properties.stream() .anyMatch(property -> property.getId().equals("cm:name"))); } - private void shouldContainAspectProperties(List properties) + private void shouldContainAspectProperties(List properties) { - NodeDefinitionProperty mandatoryAspectProperty = properties.stream() + PropertyDefinition mandatoryAspectProperty = properties.stream() .filter(property -> property.getId().equals("cm:created")) .findFirst() .get(); assertNotNull(mandatoryAspectProperty); - NodeDefinitionProperty nodeAspectProperty = properties.stream() + PropertyDefinition nodeAspectProperty = properties.stream() .filter(property -> property.getId().equals("cm:title")) .findFirst() .get(); assertNotNull(nodeAspectProperty); } - private void checkPropertyConstraints(List constraints) + private void checkPropertyConstraints(List constraints) { assertNotNull(constraints); - NodeDefinitionConstraint nodeDefinitionConstraint = constraints.stream() + ConstraintDefinition constraintDefinition = constraints.stream() .filter(constraint -> constraint.getId().equals("cm:filename")) .findFirst() .get(); - assertNotNull(nodeDefinitionConstraint); - assertEquals("REGEX", nodeDefinitionConstraint.getType()); - Map constraintParameters = nodeDefinitionConstraint.getParameters(); + assertNotNull(constraintDefinition); + assertEquals("REGEX", constraintDefinition.getType()); + Map constraintParameters = constraintDefinition.getParameters(); assertNotNull(constraintParameters); - assertNull(nodeDefinitionConstraint.getDescription()); - assertNull(nodeDefinitionConstraint.getTitle()); + assertNull(constraintDefinition.getDescription()); + assertNull(constraintDefinition.getTitle()); assertEquals(2, constraintParameters.size()); assertEquals("(.*[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)", constraintParameters.get("expression")); assertFalse((Boolean) constraintParameters.get("requiresMatch")); 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 new file mode 100644 index 0000000000..ab6ec1a841 --- /dev/null +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/TestAspects.java @@ -0,0 +1,244 @@ +/* + * #%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.tests; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + + +public class TestAspects extends AbstractBaseApiTest +{ + + private PublicApiClient.Paging paging = getPaging(0, 10); + PublicApiClient.ListResponse aspects = null; + org.alfresco.rest.api.tests.client.data.Aspect aspect, childAspect = null, smartFilter = null, rescanAspect = null; + Map otherParams = new HashMap<>(); + + @Before + public void setup() throws Exception + { + super.setup(); + + 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"); + + rescanAspect = new org.alfresco.rest.api.tests.client.data.Aspect(); + rescanAspect.setId("test:rescan"); + rescanAspect.setTitle("rescan"); + rescanAspect.setDescription("Doc that required to scan "); + + 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"); + } + + @Test + public void testAllAspects() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertTrue(aspects.getPaging().getTotalItems() > 135); + assertTrue(aspects.getPaging().getHasMoreItems()); + + paging.setSkipCount(130); + paging.setMaxItems(50); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertFalse(aspects.getPaging().getHasMoreItems()); + } + + @Test + public void filterAspectsByNamespace() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(namespaceUri matches('http://www.mycompany.com/model.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(4)); + assertFalse(aspects.getPaging().getHasMoreItems()); + + otherParams.put("where", "(not namespaceUri matches('http://www.mycompany.com/model.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertTrue(aspects.getPaging().getTotalItems() > 130); + assertTrue(aspects.getPaging().getHasMoreItems()); + } + + @Test + public void filterAspectsByParentId() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(1).expected(childAspect); + 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.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(0).expected(smartFilter); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(1)); + + otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable') AND not namespaceUri matches('http://www.test.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(1).expected(childAspect); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(3)); + + // match everything + otherParams.put("where", "(parentIds in ('smf:smartFolder','cm:auditable') 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('.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(0)); + } + + @Test + public void filterAspectsByModelId() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelIds 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.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + aspects.getList().get(0).expected(rescanAspect); + aspects.getList().get(1).expected(smartFilter); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(2)); + + otherParams.put("where", "(modelIds 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('.*'))"); + 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('.*'))"); + aspects = publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + assertEquals(aspects.getPaging().getTotalItems(), Integer.valueOf(0)); + } + + @Test + public void testAspectsById() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + aspect = publicApiClient.aspects().getAspect("mycompany:childAspect"); + aspect.expected(childAspect); + } + + @Test + public void testListAspectByInvalidValue() throws PublicApiException + { + 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("(namespaceUri matches('*'))"); // wrong pattern + } + + @Test + public void testGetAspectByInvalidValue() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + testGetAspectExceptions("unknown:childAspect"); + testGetAspectExceptions("aspect:"); + testGetAspectExceptions("aspect"); + } + + + private void testGetAspectExceptions(String aspectId) + { + try + { + publicApiClient.aspects().getAspect(aspectId); + fail("Aspect not found expected"); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + private void testListAspectException(String query) + { + try + { + otherParams.put("where", query); + publicApiClient.aspects().getAspects(createParams(paging, otherParams)); + fail("Bad request expected"); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + } + + + @Override + public String getScope() + { + return "public"; + } +} 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 new file mode 100644 index 0000000000..e8d4d59f59 --- /dev/null +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/TestTypes.java @@ -0,0 +1,238 @@ +/* + * #%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.tests; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + + +public class TestTypes extends AbstractBaseApiTest +{ + + private PublicApiClient.Paging paging = getPaging(0, 10); + PublicApiClient.ListResponse types = null; + org.alfresco.rest.api.tests.client.data.Type type = null, whitePaperType = null, docType = null; + Map otherParams = new HashMap<>(); + + @Before + public void setup() throws Exception + { + super.setup(); + whitePaperType = new org.alfresco.rest.api.tests.client.data.Type(); + whitePaperType.setId("mycompany:whitepaper"); + whitePaperType.setTitle("whitepaper"); + whitePaperType.setDescription("Whitepaper"); + whitePaperType.setParentId("mycompany:doc"); + + docType = new org.alfresco.rest.api.tests.client.data.Type(); + docType.setId("mycompany:doc"); + docType.setTitle("doc"); + docType.setDescription("Doc"); + docType.setParentId("cm:content"); + } + + @Test + public void testAllTypes() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertTrue(types.getPaging().getTotalItems() > 135); + assertTrue(types.getPaging().getHasMoreItems()); + + paging.setSkipCount(130); + paging.setMaxItems(50); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertFalse(types.getPaging().getHasMoreItems()); + } + + @Test + public void filterTypesByNamespace() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(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", "(not namespaceUri matches('http://www.mycompany.com/model.*'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertTrue(types.getPaging().getTotalItems() > 130); + } + + @Test + public void filterTypesByParentId() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(parentIds 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.*'))"); + 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.*'))"); + 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('.*'))"); + 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('.*'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(0)); + } + + @Test + public void filterTypesByModelId() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + otherParams.put("where", "(modelIds in ('mycompany:model','test:scan'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(3)); + + otherParams.put("where", "(modelIds 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.*'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(1)); + + // match everything + otherParams.put("where", "(modelIds in ('mycompany:model','test:scan') AND namespaceUri matches('.*'))"); + types = publicApiClient.types().getTypes(createParams(paging, otherParams)); + assertEquals(types.getPaging().getTotalItems(), Integer.valueOf(3)); + + // match nothing + otherParams.put("where", "(modelIds 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 testTypesById() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + type = publicApiClient.types().getType("mycompany:whitepaper"); + type.expected(whitePaperType); + } + + @Test + public void testListTypeByInvalidValue() throws PublicApiException + { + 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=' , , ')"); + 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(""); + testListTypeException("(namespaceUri matches('*'))"); // wrong pattern + } + + @Test + public void testGetTypeByInvalidValue() throws PublicApiException + { + AuthenticationUtil.setRunAsUser(user1); + publicApiClient.setRequestContext(new RequestContext(networkOne.getId(), user1)); + + testGetTypeExceptions("unknown:childType"); + testGetTypeExceptions("type:"); + testGetTypeExceptions("type"); + } + + + private void testGetTypeExceptions(String typeId) + { + try + { + publicApiClient.types().getType(typeId); + fail("type not found expected"); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + private void testListTypeException(String query) + { + try + { + otherParams.put("where", query); + publicApiClient.types().getTypes(createParams(paging, otherParams)); + fail("Bad request expected"); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + } + + + @Override + public String getScope() + { + return "public"; + } +} diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java index c72398ba15..836d21cee6 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java @@ -52,6 +52,7 @@ import org.alfresco.rest.api.tests.TestSites; import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; import org.alfresco.rest.api.tests.client.PublicApiHttpClient.RequestBuilder; import org.alfresco.rest.api.tests.client.data.Action; +import org.alfresco.rest.api.tests.client.data.Aspect; import org.alfresco.rest.api.tests.client.data.Activities; import org.alfresco.rest.api.tests.client.data.Activity; import org.alfresco.rest.api.tests.client.data.AuditApp; @@ -77,6 +78,7 @@ import org.alfresco.rest.api.tests.client.data.SiteMember; import org.alfresco.rest.api.tests.client.data.SiteGroup; import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; import org.alfresco.rest.api.tests.client.data.Tag; +import org.alfresco.rest.api.tests.client.data.Type; import org.alfresco.rest.api.tests.util.RestApiUtil; import org.apache.chemistry.opencmis.client.api.CmisObject; import org.apache.chemistry.opencmis.client.api.Document; @@ -133,7 +135,8 @@ public class PublicApiClient private RawProxy rawProxy; private AuditApps auditApps; private Actions actions; - + private Aspects aspects; + private Types types; private ThreadLocal rc = new ThreadLocal(); private ObjectMapper objectMapper = new ObjectMapper(); @@ -159,6 +162,8 @@ public class PublicApiClient rawProxy = new RawProxy(); auditApps = new AuditApps(); actions = new Actions(); + aspects = new Aspects(); + types = new Types(); } public void setRequestContext(RequestContext rc) @@ -234,7 +239,17 @@ public class PublicApiClient { return actions; } - + + public Aspects aspects() + { + return aspects; + } + + public Types types() + { + return types; + } + public CmisSession createPublicApiCMISSession(Binding binding, String version) { return createPublicApiCMISSession(binding, version, null); @@ -1670,6 +1685,36 @@ public class PublicApiClient } } + public class Aspects extends AbstractProxy + { + public PublicApiClient.ListResponse getAspects(Map params) throws PublicApiException + { + HttpResponse response = getAll("aspects", null, null, null, params, "Failed to get aspects"); + return Aspect.parseAspects(response.getJsonResponse()); + } + + public Aspect getAspect(String aspectId) throws PublicApiException + { + HttpResponse response = getAll("aspects", aspectId, null, null, null, "Failed to get aspect"); + return Aspect.parseAspect((JSONObject)response.getJsonResponse().get("entry")); + } + } + + public class Types extends AbstractProxy + { + public PublicApiClient.ListResponse getTypes(Map params) throws PublicApiException + { + HttpResponse response = getAll("types", null, null, null, params, "Failed to get types"); + return Type.parseTypes(response.getJsonResponse()); + } + + public Type getType(String typeId) throws PublicApiException + { + HttpResponse response = getAll("types", typeId, null, null, null, "Failed to get type"); + return Type.parseType((JSONObject)response.getJsonResponse().get("entry")); + } + } + public static class ExpectedPaging { private int skipCount; 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 new file mode 100644 index 0000000000..a1650bda16 --- /dev/null +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Aspect.java @@ -0,0 +1,126 @@ +/* + * #%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.tests.client.data; + +import org.alfresco.rest.api.model.PropertyDefinition; +import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class Aspect extends org.alfresco.rest.api.model.Aspect implements Serializable, ExpectedComparison +{ + + @Override + public void expected(Object model) + { + assertTrue("model is an instance of " + model.getClass(), model instanceof Aspect); + + Aspect other = (Aspect) model; + + AssertUtil.assertEquals("id", getId(), other.getId()); + AssertUtil.assertEquals("title", getTitle(), other.getTitle()); + AssertUtil.assertEquals("description", getDescription(), other.getDescription()); + AssertUtil.assertEquals("parenId", getParentId(), other.getParentId()); + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject jsonObject = new JSONObject(); + if (getId() != null) + { + jsonObject.put("id", getId()); + } + + jsonObject.put("title", getTitle()); + + if (getParentId() != null) + { + jsonObject.put("parentId", getParentId()); + } + + if (getDescription() != null) + { + jsonObject.put("description", getDescription()); + } + + if (getProperties() != null) + { + jsonObject.put("properties", getProperties()); + } + + return jsonObject; + } + + @SuppressWarnings("unchecked") + public static Aspect parseAspect(JSONObject jsonObject) + { + String id = (String) jsonObject.get("id"); + String title = (String) jsonObject.get("title"); + String description = (String) jsonObject.get("description"); + String parentId = (String) jsonObject.get("parentId"); + List properties = (List) jsonObject.get("properties"); + + Aspect action = new Aspect(); + action.setId(id); + action.setTitle(title); + action.setDescription(description); + action.setParentId(parentId); + action.setProperties(properties); + + return action; + } + + @SuppressWarnings("unchecked") + public static PublicApiClient.ListResponse parseAspects(JSONObject jsonObject) + { + List aspects = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + aspects.add(parseAspect(entry)); + } + + PublicApiClient.ExpectedPaging paging = PublicApiClient.ExpectedPaging.parsePagination(jsonList); + return new PublicApiClient.ListResponse(paging, aspects); + } + +} diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java index 91bd1cd73d..41cf597aad 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java @@ -27,7 +27,7 @@ package org.alfresco.rest.api.tests.client.data; import org.alfresco.rest.api.model.AssocChild; import org.alfresco.rest.api.model.AssocTarget; -import org.alfresco.rest.api.model.NodeDefinition; +import org.alfresco.rest.api.model.ClassDefinition; import org.alfresco.rest.api.model.NodePermissions; import java.util.Date; @@ -80,7 +80,7 @@ public class Node protected List allowableOperations; protected NodePermissions nodePermissions; - protected NodeDefinition definition; + protected ClassDefinition definition; // please note: these are currently only used (optionally) for node create request protected String relativePath; @@ -325,12 +325,12 @@ public class Node this.targets = targets; } - public NodeDefinition getDefinition() + public ClassDefinition getDefinition() { return definition; } - public void setDefinition(NodeDefinition definition) + public void setDefinition(ClassDefinition definition) { this.definition = definition; } 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 new file mode 100644 index 0000000000..68f77454c6 --- /dev/null +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/client/data/Type.java @@ -0,0 +1,126 @@ +/* + * #%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.tests.client.data; + +import org.alfresco.rest.api.model.PropertyDefinition; +import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class Type extends org.alfresco.rest.api.model.Type implements Serializable, ExpectedComparison +{ + + @Override + public void expected(Object model) + { + assertTrue("model is an instance of " + model.getClass(), model instanceof Type); + + Type other = (Type) model; + + AssertUtil.assertEquals("id", getId(), other.getId()); + AssertUtil.assertEquals("title", getTitle(), other.getTitle()); + AssertUtil.assertEquals("description", getDescription(), other.getDescription()); + AssertUtil.assertEquals("parenId", getParentId(), other.getParentId()); + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject jsonObject = new JSONObject(); + if (getId() != null) + { + jsonObject.put("id", getId()); + } + + jsonObject.put("title", getTitle()); + + if (getParentId() != null) + { + jsonObject.put("parentId", getParentId()); + } + + if (getDescription() != null) + { + jsonObject.put("description", getDescription()); + } + + if (getProperties() != null) + { + jsonObject.put("properties", getProperties()); + } + + return jsonObject; + } + + @SuppressWarnings("unchecked") + public static Type parseType(JSONObject jsonObject) + { + String id = (String) jsonObject.get("id"); + String title = (String) jsonObject.get("title"); + String description = (String) jsonObject.get("description"); + String parentId = (String) jsonObject.get("parentId"); + List properties = (List) jsonObject.get("properties"); + + Type action = new Type(); + action.setId(id); + action.setTitle(title); + action.setDescription(description); + action.setParentId(parentId); + action.setProperties(properties); + + return action; + } + + @SuppressWarnings("unchecked") + public static PublicApiClient.ListResponse parseTypes(JSONObject jsonObject) + { + List types = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + types.add(parseType(entry)); + } + + PublicApiClient.ExpectedPaging paging = PublicApiClient.ExpectedPaging.parsePagination(jsonList); + return new PublicApiClient.ListResponse(paging, types); + } + +} diff --git a/remote-api/src/test/resources/models/mycompany-model.xml b/remote-api/src/test/resources/models/mycompany-model.xml new file mode 100644 index 0000000000..793e4082f2 --- /dev/null +++ b/remote-api/src/test/resources/models/mycompany-model.xml @@ -0,0 +1,147 @@ + + Administrator + + + + + + + + + + + + + doc + Doc + cm:content + + + d:text + false + + TRUE + false + + + + d:text + false + + TRUE + false + + + + + + + + + whitepaper + Whitepaper + mycompany:doc + + + + + + + + + + + d:boolean + false + false + + TRUE + + + + d:date + false + + TRUE + + + + + + + + + mycompany:active + + + d:int + false + 5 + + TRUE + + + + + 5 + + + 23 + + + + + + + + + + + + + Test Property + Property One Description + d:text + false + + TRUE + false + + + + + + + + + Child Aspect + Child Aspect Description + smf:smartFolder + + + Propert One + Propert One Description + d:text + false + + TRUE + false + + + + + 256 + + + 5 + + + + + + + + + + + \ No newline at end of file diff --git a/remote-api/src/test/resources/models/test-scan.xml b/remote-api/src/test/resources/models/test-scan.xml new file mode 100644 index 0000000000..20d163e941 --- /dev/null +++ b/remote-api/src/test/resources/models/test-scan.xml @@ -0,0 +1,84 @@ + + + Administrator + + + + + + + + + + + + + cm:content + + + Description + Document knowledge from ai or OCR + d:mltext + false + + TRUE + false + + + + percent + Ocr scan percent + d:double + true + + TRUE + + + + Document Typt + Document type from OCR + d:text + false + + TRUE + false + + + + + + + + + + + rescan + Doc that required to scan + + + rescanpercent + Rescan percent + d:text + false + 70 + + TRUE + false + + + + + + + + + Smart filter + Smart Filter + cm:auditable + + + + + + + \ No newline at end of file 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 9e9a284cf4..293e169f48 100644 --- a/remote-api/src/test/resources/rest-api-test-context.xml +++ b/remote-api/src/test/resources/rest-api-test-context.xml @@ -16,6 +16,8 @@ models/custom-model.xml models/bpmDelegateeModel.xml models/people-api.xml + models/mycompany-model.xml + models/test-scan.xml