Files
alfresco-community-repo/source/test-java/org/alfresco/rest/api/tests/TestCustomModel.java
Jamal Kaabi-Mofrad 7ec60dc9c2 Merged DEV to HEAD
109455: Merged modules/custommodelmanagement/HEAD to DEV.
		93923: SHA-300: Added ALFRESCO_MODEL_ADMINISTRATORS group.
		95982: SHA-401: Implemented repo service for retrieving Custom Models. (WIP)
		95983: SHA-400: Added Private REST API to retrieve custom model(s)
			- Get All models: http://localhost:8080/alfresco/api/-default-/private/alfresco/versions/1/cmm
			- Get the model: http://localhost:8080/alfresco/api/-default-/private/alfresco/versions/1/cmm/<model-name>
		95984: SHA-401: Fixed the service to return null rather than throwing an exception, when the model does not exist.
		96053: SHA-400: Modified the custom model API response to return the "status" as "ACTIVE" or "DRAFT".
		96775: SHA-542: Added support to create a custom model. (WIP)
		96779: SHA-543: Added Private REST API to create custom model(s).
			- SHA-539: Cleaned up test data.
		96850: SHA-543: Added Author and Description properties to the custom model API.
		97410: SHA-407, SHA-555: Added tests for custom model backend service and the related REST API. Also, a minor modification as a result of added tests.
		97570: Modified the CMM REST API, per Kevin's request, to return empty arrays for model's types and aspects if they don't exist.
		97731: SHA-386: Added support to activate custom models. Also, a minor modification to the backend service and REST API, based on the Alfresco REST API guidelines.
		97775: SHA-386: Added tests for custom model activation (backend service). As well as, fixed the build failure by refactoring the public API tests.
		97992: SHA-573, SHA-393, SHA-494: Added support to deactivate custom model, create a new type and create a new property group (aspect).
		97994: Fixed the test as a result of renaming the service method.
		98123: SHA-393, SHA-494: Enabled the CMM REST API to create/update Types and/or Aspects via PUT. Also added validations for aspect/type's name.
		98259: SHA-453: Added backend and REST API support to delete a custom model.
		98690: SHA-393, SHA-494, SHA-453, SHA-575: Added tests for custom model backend service and the related REST API. Also, a minor modification as a result of added tests.
		99276: SHA-549: Added backend support to update a custom model. Also, refactored the service to externalise the error messages.
			- SHA-550: Added REST API support to update a custom model.
			- SHA-619: Made sure the backend service validates the model before creating a node. 
			- SHA-623: Added checks to not allow a user to create a custom model with the same name as the bootstrapped models.
		99287: SHA-619: Added InvalidCustomModelException for the CMM service to throw when the model validation fails.
		99514: SHA-506: added backend and API support to create custom Type/Aspect properties. Also refactored the API to overcome the Public API limitations.
		99522: SHA-506: Modified the Type/Aspect JSON payload to include a new read only property "prefixedName".
		99527: Fixed Bamboo build failure as the result of r99522 commit.
		99630: SHA-506: - Updated the API to exclude the inherited properties.
			- Added API tests for creating properties.
			- Modified the Custom Properties JSON response to include a new read only attribute "prefixedName".
                99662: SHA-351: Updated the API to support 'mandatory' and 'mandatoryEnforced' properties.
			- SHA-410: Updated the API to support 'defaultValue' property.
			- SHA-506: Modified the Custom Properties JSON response to include 'description' and 'multiValued' attributes.
		99669: SHA-506: Removed the unnecessary (at least in this sprint) methods from the backend service.
		99684: SHA-638: Added checks to not allow a user to create a custom model with already in-use namespace prefix.
		99959: SHA-679: Modified the custom model API to not import the already defined namespace.
		100211: SHA-607: Modified the custom model API to support delete model's type. Also, removed the unnecessary test as we depend on the dictionary service, so no need to test it in the custom model API.
		100281: Added Types and Aspects to the GET a single model API response, when it is requested with "?select=all" query string.
		100335: Added test for "?select=all" query string within the GET a single model API (see rev 100281).
		100366: SHA-612: Modified the custom model API to support delete model's aspect.
		100738: SHA-698: Added checks so the model Admin is not allowed to deactivate a custom model when its types/aspects are parent to other models' types/aspects (regardless of the model being active or not).
		100740: SHA-698: Fixed Bamboo build failures.
		101085: SHA-703: Added dependency validation before deleting custom type/aspect in the custom model API.
		101160: Modified the custom model API to return all properties (including the inherited properties) of the type/aspect, when requested by "?select=allProps".
		101636: SHA-697.
		101771: SHA-706: Made custom models hidden in the data dictionary.
		101863: SHA-701: Added checks to not allow creating duplicate properties within the same model. Also, removed unnecessary/duplicate constants from the custom model service class.
		101983: SHA-688: Fixed the error message by getting the root-cause-exception and returning its message. However, DictionaryException messages are not localised, so this will be fixed in the alfresco core.
		102223: Fix for SHA-726: Not able to edit prefix field of deactivated model when model type is referenced within same model - The API will update the parent prefixed name with the new prefix.
			- Also, added more validations to the CMM API, when setting a type/asptect's parent.
		102587: SHA-741, SHA-745, SHA-747: Added custom model Constraints support.
		102725: SHA-784: Fixed parent validation of the type/aspect.
		103030: SHA-741, SHA-745, SHA-747: Added tests for custom model Constraints.
			- Also fixed and refactored the API code as the result of tests.
		103753: SHA-846: Added inline constraints support. Also:
			- Modified the backend CMM service to throw CustomModelConstraintException when the root cause is DuplicateDefinitionException.
			- Removed the duplicate name check from the CMM API, as now it will depend on the exceptions thrown upon model compilation.
		103885: SHA-819, SHA-833: Added support to edit existing type/aspect.
		103973: SHA-819, SHA-833: Added API tests for types/aspects Edit. Also, refactored CMM API tests by moving the tests to their corresponding test class.
		104079: SHA-808: Fixed custom models bidirectional dependency.
		104158: Deleted the ExtendedRepoAdminService class as the required functionality has been added (see SHA-879) to the core alfresco code.
		104287: SHA-843: Modified the custom model API to support delete property. Also, minor refactoring of the API tests.
		104403: SHA-842: Modified the custom model API to support Edit property.
		104475: SHA-842: Added API tests for Edit property.
		104569: SHA-913 - Remove case sensitive option from the UI
			- SHA-914 - Update PO and tests that use the case sensitive option
			- Remove case sensitive option on LIST constraint throughout
			Also:
			- Update Aikau version to 1.0.18
		104690: Fixed Bamboo build failure caused by r104569.
		104849: SHA-808: Fixed custom models circular dependencies.
		105297: SHA-807: Added property default-value and constraint (REGEX, MINMAX and LENGTH) validators.
		105642: SHA-950: Wrapped backend CMM service method with a NEW transaction, in order to catch the thrown exception within DictionaryModelTypeTransactionListener. Also refactored the CMM backend service tests as the result of this change.
		106677: SHA-888, SHA-889, SHA-890: Added Backend and API support to export a custom model and its associated Share form.
		106722: SHA-888, SHA-889, SHA-890: Fixed a few minor issues raised during code review.
		107007: ACE-4019: Modified the CMM service to not start a new TX when creating a new model.
		107070: Temporarily enabled (hard coded) index and facetable attributes in the custom model properties.
		107296: GERMAN: Model Manager files localised as per EN-rev105921
		107297: FRENCH: Model Manager localised files based on EN-rev105921
		107315: SPANISH: Model Manager localised files based on EN-rev105921
		107317: JAPANESE: Model Manager localised files based on EN-rev105921
		107321: ITALIAN: Model Manager localised files based on EN-rev105921
		107322: DUTCH: Model Manager localised files based on EN-rev105921
		107335: SHA-889: Modified the CMM service to not throw an exception when exporting the model and its associated share extension module, where the Share extension module has not been created for the model yet.
		107456: SHA-893: Added API support to upload/import a custom model and its associated Share extension module.
		107560: SHA-893: Added model upload API tests as well as minor fixes.
		107647: SHA-893: Fixed minor issues raised during code review.
		107773: Docs review of message labels and errors.
		107866: SHA-1126: Added check for the maximum value of the MINMAX constraint to be a positive nonzero value.
		108117: SHA-832: Added validation for properties' default values to be checked against the property defined constraint.
		108256: SHA-1194: Modified CMM API to support indexing options.
		108510: SHA-1151: Externalised CMM rest API error messages.
			- SHA-1196: Changed the CMM Rest API input validator to use the same RegExs as the CMM Share.
		108518: SHA-1194: Changed CMM property facetable options to include "UNSET".
		108561: GERMAN: Model Manager files updated as per EN-rev107962
		108562: FRENCH: Model Manager files updated as per EN-rev107962
		108565: ITALIAN: Model Manager files updated as per EN-rev107962
		108566: SPANISH: Model Manager files updated as per EN-rev107962
		108567: JAPANESE: Model Manager files updated as per EN-rev107962
		108568: NORWEGIAN Bokmal: Model Manager files updated as per EN-rev107962
		108570: DUTCH: Model Manager files updated as per EN-rev107962
		108571: RUSSIAN: Model Manager files updated as per EN-rev107962
		108572: BRAZILIAN Portuguese: Model Manager files updated as per EN-rev107962
		108573: SIMPLIFIED CHINESE: Model Manager files updated as per EN-rev107962
		108604: Removed the unnecessary escaped quotation from the strings which don't have variables.
		108721: Api message changes from docs.
		108728: Changed "Property group" to "Aspect" in the CMM API error messages.
		108934: Added the missing escaped quotation into API messages.
		109037: Changes from docs for mandatory field character messages in the API.
		109204: ITALIAN: Updated bundle based on EN rev109039
		109205: GERMAN: Updated bundle based on EN rev109039
		109206: FRENCH: Updated bundle based on EN rev109039
		109223: GERMAN: Updated bundle based on EN rev109039 - fixed single quotes
		109226: FRENCH: Updated bundle based on EN rev109039 - fixed single quotes
		109228: ITALIAN: Updated bundle based on EN rev109039 - fixed single quotes
		109230: FRENCH: Updated bundle based on EN rev109039 - fixed single quotes again
		109235: JAPANESE: Updated bundle based on EN rev109039
		109293: SPANISH: Updated bundle based on EN rev109039
		109300: DUTCH: Updated bundle based on EN rev109039
		109412:	- Refactored the CMM JMX support to return CompositeData for performance reasons.
			- Reorganised a few of CMM classes/interfaces to make it easier for merging to alfresco core.
			- A minor fixes as a result of Find Bugs analysis.
			- Added the minimum and maximum repo versions for CMM module.
		109421: NORWEGIAN: Updated bundle based on EN rev109039
		109424: BRAZILIAN PORTUGUESE: Updated bundle based on EN rev109039
		109426: RUSSIAN: Updated bundle based on EN rev109039
		109427: CHINESE: Updated bundle based on EN rev10903
   109475: Added CMM Model into the core services (missed from previous commit).
   109480: SHA-723: Added custom models analytics in HeartBeat data.
   109481: SHA-528: Added GROUP_ALFRESCO_MODEL_ADMINISTRATORS_AUTHORITY patch.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@109490 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2015-08-04 01:56:12 +00:00

662 lines
37 KiB
Java

/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.api.model.CustomModel.ModelStatus;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient.Paging;
import org.alfresco.rest.api.tests.util.RestApiUtil;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.junit.Test;
/**
* Tests the REST API of the models of the {@link CustomModelService}.
*
* @author Jamal Kaabi-Mofrad
*/
public class TestCustomModel extends BaseCustomModelApiTest
{
@Test
public void testCreateBasicModel() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
CustomModel customModel = new CustomModel();
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setDescription("Test model description");
customModel.setStatus(CustomModel.ModelStatus.DRAFT);
// Try to create the model as a non Admin user
post("cmm", nonAdminUserName, RestApiUtil.toJsonAsString(customModel), 403);
// Create the model as a Model Administrator
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
// Retrieve the created model
HttpResponse response = getSingle("cmm", customModelAdmin, modelName, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
// Check the retrieved model is the expected model.
// Note: since we didn't specify the Author when created the Model,
// we have to exclude it from the objects comparison. Because,
// the system will add the current authenticated user as the author
// of the model, if the Author hasn't been set.
compareCustomModels(customModel, returnedModel, "author");
}
@Test
public void testCreateBasicModel_Invalid() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
CustomModel customModel = new CustomModel();
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
// Test invalid inputs
{
customModel.setName(modelName + "<script>alert('oops')</script>");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400);
customModel.setName("prefix:" + modelName);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid name. Contains ':'
customModel.setName("prefix " + modelName);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid name. Contains space
customModel.setName(modelName);
customModel.setNamespacePrefix(namespacePair.getSecond()+" space");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid prefix. Contains space
customModel.setNamespacePrefix(namespacePair.getSecond()+"invalid/");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid prefix. Contains '/'
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setNamespaceUri(namespacePair.getFirst()+" space");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid URI. Contains space
customModel.setNamespaceUri(namespacePair.getFirst()+"\\");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid URI. Contains '\'
}
// Test mandatory properties of the model
{
customModel.setName("");
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setNamespaceUri(namespacePair.getFirst());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // name is mandatory
customModel.setName(modelName);
customModel.setNamespaceUri(null);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // namespaceUri is mandatory
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(null);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // namespacePrefix is mandatory
}
// Test duplicate model name
{
// Test create a model with the same name as the bootstrapped model
customModel.setName("contentmodel");
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 409);
// Create the model
customModel.setName(modelName);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
// Create a duplicate model
// Set a new namespace to make sure the 409 status code is returned
// because of a name conflict rather than namespace URI
namespacePair = getTestNamespaceUriPrefixPair();
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 409);
}
// Test duplicate namespaceUri
{
String modelNameTwo = "testModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
CustomModel customModelTwo = new CustomModel();
customModelTwo.setName(modelNameTwo);
customModelTwo.setNamespaceUri(namespacePairTwo.getFirst());
customModelTwo.setNamespacePrefix(namespacePairTwo.getSecond());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModelTwo), 201);
String modelNameThree = "testModelThree" + System.currentTimeMillis();
Pair<String, String> namespacePairThree = getTestNamespaceUriPrefixPair();
CustomModel customModelThree = new CustomModel();
customModelThree.setName(modelNameThree);
customModelThree.setNamespaceUri(namespacePairTwo.getFirst()); // duplicate URI
customModelThree.setNamespacePrefix(namespacePairThree.getSecond());
// Try to create a model with a namespace uri which has already been used.
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModelThree), 409);
customModelThree.setNamespaceUri(namespacePairThree.getFirst());
customModelThree.setNamespacePrefix(namespacePairTwo.getSecond()); // duplicate prefix
// Try to create a model with a namespace prefix which has already been used.
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModelThree), 409);
}
}
@Test
public void testListBasicModels() throws Exception
{
String modelName_1 = "testModel1" + System.currentTimeMillis();
// Create the model as a Model Administrator
CustomModel customModel_1 = createCustomModel(modelName_1, getTestNamespaceUriPrefixPair(), ModelStatus.DRAFT);
String modelName_2 = "testModel2" + System.currentTimeMillis();
CustomModel customModel_2 = createCustomModel(modelName_2, getTestNamespaceUriPrefixPair(), ModelStatus.DRAFT);
String modelName_3 = "testModel3" + System.currentTimeMillis();
CustomModel customModel_3 = createCustomModel(modelName_3, getTestNamespaceUriPrefixPair(), ModelStatus.DRAFT);
Paging paging = getPaging(0, Integer.MAX_VALUE);
HttpResponse response = getAll("cmm", customModelAdmin, paging, 200);
List<CustomModel> models = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), CustomModel.class);
assertTrue(models.size() >= 3);
assertTrue(models.contains(customModel_1));
assertTrue(models.contains(customModel_2));
assertTrue(models.contains(customModel_3));
}
@Test
public void testActivateCustomModel() throws Exception
{
String modelNameOne = "testActivateModelOne" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
CustomModel customModelOne = createCustomModel(modelNameOne, namespacePair, ModelStatus.DRAFT, "Test model description", "Jane Doe");
// Retrieve the created model and check its status (the default is DRAFT)
HttpResponse response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.DRAFT, returnedModel.getStatus());
// We only want to update the status, so ignore the other properties
CustomModel updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.ACTIVE);
// Try to activate the model as a non Admin user
put("cmm", nonAdminUserName, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 403);
// Activate the model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Check other properties have not been modified
compareCustomModels(customModelOne, returnedModel, "status");
// Try to activate the already activated model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 500);
// Create another Model
String modelNameTwo = "testActivateModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
CustomModel customModelTwo = createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT, null, "John Doe");
// Activate the model as a Model Administrator
customModelTwo.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(customModelTwo), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameTwo, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Check other properties have not been modified
compareCustomModels(customModelTwo, returnedModel, "status");
}
@Test
public void testDeactivateCustomModel() throws Exception
{
String modelNameOne = "testDeactivateModelOne" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
CustomModel customModelOne = createCustomModel(modelNameOne, namespacePair, ModelStatus.ACTIVE, null, "Mark Moe");
// Retrieve the created model and check its status
HttpResponse response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// We only want to update the status (Deactivate), so ignore the other properties
CustomModel updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.DRAFT);
// Try to deactivate the model as a non Admin user
put("cmm", nonAdminUserName, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 403);
// Deactivate the model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.DRAFT, returnedModel.getStatus());
// Check other properties have not been modified
compareCustomModels(customModelOne, returnedModel, "status");
// Try to deactivate the already deactivated model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 500);
// Activate/Deactivate a model with an aspect
{
// Create another Model
final String modelNameTwo = "testDeactivateModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
CustomModel customModelTwo = createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT, null, "Mark Moe");
// Aspect
CustomAspect aspect = new CustomAspect();
aspect.setName("testMarkerAspect");
post("cmm/" + modelNameTwo + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 201);
// Retrieve the created aspect
getSingle("cmm/" + modelNameTwo + "/aspects", customModelAdmin, aspect.getName(), 200);
// Activate the model as a Model Administrator
customModelTwo.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(customModelTwo), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameTwo, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.DRAFT);
// Deactivate the model as a Model Administrator
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameTwo, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.DRAFT, returnedModel.getStatus());
}
}
@Test
public void testDeleteCustomModel() throws Exception
{
String modelName = "testDeleteModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
CustomModel customModel = createCustomModel(modelName, namespacePair, ModelStatus.DRAFT, null, "Joe Bloggs");
// Retrieve the created model
HttpResponse response = getSingle("cmm", customModelAdmin, modelName, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
compareCustomModels(customModel, returnedModel);
// Try to delete the model as a non Admin user
delete("cmm", nonAdminUserName, modelName, 403);
// Delete the model as a Model Administrator
delete("cmm", customModelAdmin, modelName, 204);
// Create the model again
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
// Activated the model
CustomModel updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
// Try to delete the active model
delete("cmm", customModelAdmin, modelName, 409);
// Deactivate and then delete the model
updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
delete("cmm", customModelAdmin, modelName, 204);
}
@Test
public void testUpdateBasicModel() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT, "Test model description", null);
//Test update name
CustomModel updatePayload = new CustomModel();
String newName = modelName + "Modified";
updatePayload.setName(newName);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 400); // Cannot update the model name
// Test update the namespace URI (already in-use)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri("http://www.alfresco.org/model/content/1.0");
updatePayload.setNamespacePrefix("newPrefix");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409); // The namespace uri has already been used
// Test update the namespace Prefix (already in-use)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(getTestNamespaceUriPrefixPair().getFirst());
updatePayload.setNamespacePrefix("cm");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409); // The namespace prefix has already been used
// Test update the namespace URI (without sending the namespace prefix)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(getTestNamespaceUriPrefixPair().getFirst());
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 400); // The namespace prefix is mandatory
// Test update the namespace URI only
updatePayload = new CustomModel();
updatePayload.setNamespacePrefix( namespacePair.getSecond());
Pair<String, String> newURI = getTestNamespaceUriPrefixPair();
updatePayload.setNamespaceUri(newURI.getFirst());
HttpResponse response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(newURI.getFirst(), returnedModel.getNamespaceUri());
assertEquals("The namespace prefix shouldn't have changed.", namespacePair.getSecond(), returnedModel.getNamespacePrefix());
// Test update the namespace prefix (without sending the namespace URI)
updatePayload = new CustomModel();
updatePayload.setNamespacePrefix("newPrefix");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 400); // The namespce uri is mandatory
// Test update the namespace prefix only
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(namespacePair.getFirst());
Pair<String, String> newPrefix = getTestNamespaceUriPrefixPair();
updatePayload.setNamespacePrefix( newPrefix.getSecond());
response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(newPrefix.getSecond(), returnedModel.getNamespacePrefix());
assertEquals("The namespace URI shouldn't have changed.", namespacePair.getFirst(), returnedModel.getNamespaceUri());
// Test a valid update
updatePayload = new CustomModel();
Pair<String, String> newNamespacePair = getTestNamespaceUriPrefixPair();
updatePayload.setNamespaceUri(newNamespacePair.getFirst());
updatePayload.setNamespacePrefix(newNamespacePair.getSecond());
updatePayload.setDescription("Test model description Modified");
updatePayload.setAuthor("John Moe");
updatePayload.setStatus(ModelStatus.ACTIVE); // This should be ignored
// Try to update the model as a non Admin user
put("cmm", nonAdminUserName, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 403);
// Update the model as a Model Administrator
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
// Retrieve the updated model
response = getSingle("cmm", customModelAdmin, modelName, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
compareCustomModels(updatePayload, returnedModel, "name", "status");
assertEquals("The model status should only be updated via '?select=status' request.", ModelStatus.DRAFT, returnedModel.getStatus());
// Activate the model as a Model Administrator
updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.ACTIVE);
response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Try to update the ACTIVE model's namespace URI
updatePayload = new CustomModel();
newNamespacePair = getTestNamespaceUriPrefixPair();
updatePayload.setNamespaceUri(newNamespacePair.getFirst());
updatePayload.setNamespacePrefix(returnedModel.getNamespacePrefix());
// Cannot update the namespace uri and/or namespace prefix when the model is Active.
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409);
// Try to update the ACTIVE model's namespace Prefix
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(returnedModel.getNamespaceUri());
updatePayload.setNamespacePrefix("myNewPrefix");
// Cannot update the namespace uri and/or namespace prefix when the model is Active.
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409);
// Test a valid update of an Active model (you can only update desc and author)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(returnedModel.getNamespaceUri());
updatePayload.setNamespacePrefix(returnedModel.getNamespacePrefix());
updatePayload.setDescription("Test modifying active model description");
updatePayload.setAuthor("Mark Miller");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
// Retrieve the updated active model
response = getSingle("cmm", customModelAdmin, modelName, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
compareCustomModels(updatePayload, returnedModel, "name", "status");
}
@Test
//SHA-726
public void testUpdateModel_WithAspectsAndTypes() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
// Add type
String typeBaseName = "testTypeBase" + System.currentTimeMillis();
final String typeBaseNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeBaseName;
createTypeAspect(CustomType.class, modelName, typeBaseName, "test typeBase title", null, "cm:content");
// Add aspect
final String aspectName = "testAspect" + System.currentTimeMillis();
final String aspectNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + aspectName;
createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Activate the model
CustomModel modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
// Add another type with 'typeBaseName' as its parent
String childTypeName = "testTypeChild" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, childTypeName, "test typeChild title", "test typeChild Desc", typeBaseNameWithPrefix);
// Add another aspect with 'aspectName' as its parent
final String childAspectName = "testChildAspect" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, childAspectName, "test child aspect title", null, aspectNameWithPrefix);
// Deactivate the model
modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
// Test update the namespace prefix
CustomModel updatePayload = new CustomModel();
String modifiedPrefix = namespacePair.getSecond() + "Modified";
updatePayload.setNamespacePrefix(modifiedPrefix);
updatePayload.setNamespaceUri(namespacePair.getFirst());
HttpResponse response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(modifiedPrefix, returnedModel.getNamespacePrefix());
assertEquals("The namespace URI shouldn't have changed.", namespacePair.getFirst(), returnedModel.getNamespaceUri());
// Test update the namespace URI
updatePayload = new CustomModel();
updatePayload.setNamespacePrefix(modifiedPrefix);
String modifiedURI = namespacePair.getFirst() + "Modified";
updatePayload.setNamespaceUri(modifiedURI);
response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(modifiedURI, returnedModel.getNamespaceUri());
assertEquals("The namespace prefix shouldn't have changed.", modifiedPrefix, returnedModel.getNamespacePrefix());
// Retrieve the child type
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, childTypeName, 200);
CustomType returnedChildType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
final String newTypeParentName = modifiedPrefix + QName.NAMESPACE_PREFIX + typeBaseName;
assertEquals("The parent name prefix should have been updated.", newTypeParentName, returnedChildType.getParentName());
// Retrieve the child aspect
response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, childAspectName, 200);
CustomAspect returnedChildAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
final String newAspectParentName = modifiedPrefix + QName.NAMESPACE_PREFIX + aspectName;
assertEquals("The parent name prefix should have been updated.", newAspectParentName, returnedChildAspect.getParentName());
}
// SHA-808
@Test
public void testModelsCircularDependency() throws Exception
{
// Model One
String modelNameOne = "testModelOne" + System.currentTimeMillis();
Pair<String, String> namespacePairOne = getTestNamespaceUriPrefixPair();
// Create the modelOne as a Model Administrator
createCustomModel(modelNameOne, namespacePairOne, ModelStatus.DRAFT);
// Add typeA_M1 into modelOne
String typeA_M1 = "testTypeA_M1" + System.currentTimeMillis();
final String typeA_M1_WithPrefix = namespacePairOne.getSecond() + QName.NAMESPACE_PREFIX + typeA_M1;
createTypeAspect(CustomType.class, modelNameOne, typeA_M1, "test typeA_M1 title", null, "cm:content");
// Activate modelOne
CustomModel modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
// Add another type into modelOne with 'typeA_M1' as its parent
String typeB_M1 = "testTypeB_M1" + System.currentTimeMillis();
final String typeB_M1_WithPrefix = namespacePairOne.getSecond() + QName.NAMESPACE_PREFIX + typeB_M1;
createTypeAspect(CustomType.class, modelNameOne, typeB_M1, "test typeB_M1 title", "test typeB_M1 Desc", typeA_M1_WithPrefix);
// Model Two
String modelNameTwo = "testModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
// Create the modelTwo as a Model Administrator
createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT);
// Add type1_M2 into modelTwo with 'typeB_M1' (from modelOne) as its parent
String type1_M2 = "testType1_M2" + System.currentTimeMillis();
final String type1_M2_WithPrefix = namespacePairTwo.getSecond() + QName.NAMESPACE_PREFIX + type1_M2;
createTypeAspect(CustomType.class, modelNameTwo, type1_M2, "test type1_M2 title", null, typeB_M1_WithPrefix );
// Activate modelTwo
CustomModel modelTwoStatusPayload = new CustomModel();
modelTwoStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(modelTwoStatusPayload), SELECT_STATUS_QS, 200);
// Test that the API can handle "circular dependency" - (modelOne depends on modelTwo)
{
// Add another type into modelOne with 'type1_M2' (from modelTwo) as its parent
String typeC_M1 = "testTypeC_M1" + System.currentTimeMillis();
CustomType typeC_M1_Payload = new CustomType();
typeC_M1_Payload.setName(typeC_M1);
typeC_M1_Payload.setTitle("test typeC_M1 title");
typeC_M1_Payload.setParentName(type1_M2_WithPrefix); // => 'type1_M2' (from modelTwo)
// Try to create typeC_M1 which has 'circular dependency'
post("cmm/" + modelNameOne + "/types", customModelAdmin, RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation
}
// Model Three
String modelNameThree = "testModelThree" + System.currentTimeMillis();
Pair<String, String> namespacePairThree = getTestNamespaceUriPrefixPair();
// Create the modelThree as a Model Administrator
createCustomModel(modelNameThree, namespacePairThree, ModelStatus.DRAFT);
// Add type1_M3 into modelThree with 'type1_M2' (from modelTwo) as its parent
String type1_M3 = "testType1_M3" + System.currentTimeMillis();
final String type1_M3_WithPrefix = namespacePairThree.getSecond() + QName.NAMESPACE_PREFIX + type1_M3;
createTypeAspect(CustomType.class, modelNameThree, type1_M3, "test type1_M3 title", null, type1_M2_WithPrefix );
// Activate modelThree
CustomModel modelThreeStatusPayload = new CustomModel();
modelThreeStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameThree, RestApiUtil.toJsonAsString(modelThreeStatusPayload), SELECT_STATUS_QS, 200);
// Test that the API can handle "circular dependency" - (modelOne depends on modelThree)
{
// Add another type into modelOne with 'type1_M3' (from modelThree) as its parent
String typeC_M1 = "testTypeC_M1" + System.currentTimeMillis();
CustomType typeC_M1_Payload = new CustomType();
typeC_M1_Payload.setName(typeC_M1);
typeC_M1_Payload.setTitle("test typeC_M1 title");
typeC_M1_Payload.setParentName(type1_M3_WithPrefix); // => 'type1_M3' (from modelThree)
// Try to create typeC_M1 which has 'circular dependency'
post("cmm/" + modelNameOne + "/types", customModelAdmin, RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation
}
// Model Three
String modelNameFour = "testModelFour" + System.currentTimeMillis();
Pair<String, String> namespacePairFour = getTestNamespaceUriPrefixPair();
// Create the modelFour as a Model Administrator
createCustomModel(modelNameFour, namespacePairFour, ModelStatus.DRAFT);
// Add type1_M4 into modelFour with 'type1_M3' (from modelThree) as its parent
String type1_M4 = "testType1_M4" + System.currentTimeMillis();
final String type1_M4_WithPrefix = namespacePairFour.getSecond() + QName.NAMESPACE_PREFIX + type1_M4;
createTypeAspect(CustomType.class, modelNameFour, type1_M4, "test type1_M4 title", null, type1_M3_WithPrefix );
// Activate modelFour
CustomModel modelFourStatusPayload = new CustomModel();
modelFourStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameFour, RestApiUtil.toJsonAsString(modelFourStatusPayload), SELECT_STATUS_QS, 200);
// Test that the API can handle "circular dependency" - (modelOne depends on modelFour)
{
// Add another type into modelOne with 'type1_M4' (from modelFour) as its parent
String typeC_M1 = "testTypeC_M1" + System.currentTimeMillis();
CustomType typeC_M1_Payload = new CustomType();
typeC_M1_Payload.setName(typeC_M1);
typeC_M1_Payload.setTitle("test typeC_M1 title");
typeC_M1_Payload.setParentName(type1_M4_WithPrefix); // => 'type1_M4' (from modelFour)
// Try to create typeC_M1 which has 'circular dependency'
post("cmm/" + modelNameOne + "/types", customModelAdmin, RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation
}
// Test that the API can handle "circular dependency" - (modelTwo depends on modelFour)
{
// Add another type into modelTwo with 'type1_M4' (from modelFour) as its parent
String type2_M2 = "testType2_M2" + System.currentTimeMillis();
CustomType type2_M2_Payload = new CustomType();
type2_M2_Payload.setName(type2_M2);
type2_M2_Payload.setTitle("test type2_M2 title");
type2_M2_Payload.setParentName(type1_M4_WithPrefix); // => 'type1_M4' (from modelFour)
// Try to create type2_M2 which has 'circular dependency'
post("cmm/" + modelNameTwo + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type2_M2_Payload), 409); //Constraint violation
}
}
}