/* * #%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% */ 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 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); setRequestContext(nonAdminUserName); // Try to create the model as a non Admin user post("cmm", RestApiUtil.toJsonAsString(customModel), 403); setRequestContext(customModelAdmin); // Create the model as a Model Administrator post("cmm", RestApiUtil.toJsonAsString(customModel), 201); // Retrieve the created model HttpResponse response = getSingle("cmm", 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 namespacePair = getTestNamespaceUriPrefixPair(); CustomModel customModel = new CustomModel(); customModel.setName(modelName); customModel.setNamespaceUri(namespacePair.getFirst()); customModel.setNamespacePrefix(namespacePair.getSecond()); setRequestContext(customModelAdmin); // Test invalid inputs { customModel.setName(modelName + ""); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); customModel.setName("prefix:" + modelName); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); // Invalid name. Contains ':' customModel.setName("prefix " + modelName); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); // Invalid name. Contains space customModel.setName(modelName); customModel.setNamespacePrefix(namespacePair.getSecond()+" space"); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); // Invalid prefix. Contains space customModel.setNamespacePrefix(namespacePair.getSecond()+"invalid/"); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); // Invalid prefix. Contains '/' customModel.setNamespacePrefix(namespacePair.getSecond()); customModel.setNamespaceUri(namespacePair.getFirst()+" space"); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); // Invalid URI. Contains space customModel.setNamespaceUri(namespacePair.getFirst()+"\\"); post("cmm", 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", RestApiUtil.toJsonAsString(customModel), 400); // name is mandatory customModel.setName(modelName); customModel.setNamespaceUri(null); post("cmm", RestApiUtil.toJsonAsString(customModel), 400); // namespaceUri is mandatory customModel.setName(modelName); customModel.setNamespaceUri(namespacePair.getFirst()); customModel.setNamespacePrefix(null); post("cmm", 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", RestApiUtil.toJsonAsString(customModel), 409); // Create the model customModel.setName(modelName); post("cmm", 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", RestApiUtil.toJsonAsString(customModel), 409); } // Test duplicate namespaceUri { String modelNameTwo = "testModelTwo" + System.currentTimeMillis(); Pair namespacePairTwo = getTestNamespaceUriPrefixPair(); CustomModel customModelTwo = new CustomModel(); customModelTwo.setName(modelNameTwo); customModelTwo.setNamespaceUri(namespacePairTwo.getFirst()); customModelTwo.setNamespacePrefix(namespacePairTwo.getSecond()); post("cmm", RestApiUtil.toJsonAsString(customModelTwo), 201); String modelNameThree = "testModelThree" + System.currentTimeMillis(); Pair 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", 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", RestApiUtil.toJsonAsString(customModelThree), 409); } } @Test public void testListBasicModels() throws Exception { setRequestContext(customModelAdmin); 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", paging, 200); List 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 { setRequestContext(customModelAdmin); String modelNameOne = "testActivateModelOne" + System.currentTimeMillis(); Pair 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", 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); setRequestContext(nonAdminUserName); // Try to activate the model as a non Admin user put("cmm", modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 403); setRequestContext(customModelAdmin); // Activate the model as a Model Administrator put("cmm", modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200); response = getSingle("cmm", 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", modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 500); // Create another Model String modelNameTwo = "testActivateModelTwo" + System.currentTimeMillis(); Pair 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", modelNameTwo, RestApiUtil.toJsonAsString(customModelTwo), SELECT_STATUS_QS, 200); response = getSingle("cmm", 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 { setRequestContext(customModelAdmin); String modelNameOne = "testDeactivateModelOne" + System.currentTimeMillis(); Pair 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", 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); setRequestContext(nonAdminUserName); // Try to deactivate the model as a non Admin user put("cmm", modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 403); setRequestContext(customModelAdmin); // Deactivate the model as a Model Administrator put("cmm", modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200); response = getSingle("cmm", 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", 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 namespacePairTwo = getTestNamespaceUriPrefixPair(); CustomModel customModelTwo = createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT, null, "Mark Moe"); // Aspect CustomAspect aspect = new CustomAspect(); aspect.setName("testMarkerAspect"); post("cmm/" + modelNameTwo + "/aspects", RestApiUtil.toJsonAsString(aspect), 201); // Retrieve the created aspect getSingle("cmm/" + modelNameTwo + "/aspects", aspect.getName(), 200); // Activate the model as a Model Administrator customModelTwo.setStatus(ModelStatus.ACTIVE); put("cmm", modelNameTwo, RestApiUtil.toJsonAsString(customModelTwo), SELECT_STATUS_QS, 200); response = getSingle("cmm", 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", modelNameTwo, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200); response = getSingle("cmm", modelNameTwo, 200); returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class); assertEquals(ModelStatus.DRAFT, returnedModel.getStatus()); } } @Test public void testDeleteCustomModel() throws Exception { setRequestContext(customModelAdmin); String modelName = "testDeleteModel" + System.currentTimeMillis(); Pair 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", modelName, 200); CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class); compareCustomModels(customModel, returnedModel); setRequestContext(nonAdminUserName); // Try to delete the model as a non Admin user delete("cmm", modelName, 403); setRequestContext(customModelAdmin); // Delete the model as a Model Administrator delete("cmm", modelName, 204); // Create the model again post("cmm", RestApiUtil.toJsonAsString(customModel), 201); // Activated the model CustomModel updatePayload = new CustomModel(); updatePayload.setStatus(ModelStatus.ACTIVE); put("cmm", modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200); // Try to delete the active model delete("cmm", modelName, 409); // Deactivate and then delete the model updatePayload = new CustomModel(); updatePayload.setStatus(ModelStatus.DRAFT); put("cmm", modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200); delete("cmm", modelName, 204); } @Test public void testUpdateBasicModel() throws Exception { setRequestContext(customModelAdmin); String modelName = "testModel" + System.currentTimeMillis(); Pair 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", 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", 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", 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", 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 newURI = getTestNamespaceUriPrefixPair(); updatePayload.setNamespaceUri(newURI.getFirst()); HttpResponse response = put("cmm", 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", 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 newPrefix = getTestNamespaceUriPrefixPair(); updatePayload.setNamespacePrefix( newPrefix.getSecond()); response = put("cmm", 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 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 setRequestContext(nonAdminUserName); // Try to update the model as a non Admin user put("cmm", modelName, RestApiUtil.toJsonAsString(updatePayload), null, 403); setRequestContext(customModelAdmin); // Update the model as a Model Administrator put("cmm", modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200); // Retrieve the updated model response = getSingle("cmm", 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", 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", 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", 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", modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200); // Retrieve the updated active model response = getSingle("cmm", modelName, 200); returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class); compareCustomModels(updatePayload, returnedModel, "name", "status"); } @Test //SHA-726 public void testUpdateModel_WithAspectsAndTypes() throws Exception { setRequestContext(customModelAdmin); String modelName = "testModel" + System.currentTimeMillis(); Pair 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", 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", 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", 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", 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", 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", 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 { setRequestContext(customModelAdmin); // Model One String modelNameOne = "testModelOne" + System.currentTimeMillis(); Pair 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", 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 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", 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", RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation } // Model Three String modelNameThree = "testModelThree" + System.currentTimeMillis(); Pair 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", 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", RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation } // Model Three String modelNameFour = "testModelFour" + System.currentTimeMillis(); Pair 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", 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", 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", RestApiUtil.toJsonAsString(type2_M2_Payload), 409); //Constraint violation } } }