/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.jcr;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinitionTemplate;
import javax.jcr.nodetype.NodeTypeDefinition;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.nodetype.PropertyDefinitionTemplate;
import javax.jcr.version.OnParentVersionAction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.modeshape.common.FixFor;
public class MixinTest extends SingleUseAbstractTest {
/*
* Declares the following node types:
* mixinTypeA with child node nodeA and property propertyA
* mixinTypeB with child node nodeB and property propertyB
* mixinTypeC with child node nodeA and property propertyB
* mixinTypeWithAutoCreatedProperty with auto-created property propertyB
* mixinTypeWithAutoCreatedChildNode with auto-created child node nodeB
* mixinTypeC with child node nodeA and property propertyB
* primaryTypeA with child node nodeA and property propertyA
* mixinProtected with child node childProtected and property propertyProtected
*/
static final String MIXIN_TYPE_A = "mixinTypeA";
static final String MIXIN_TYPE_B = "mixinTypeB";
static final String MIXIN_TYPE_C = "mixinTypeC";
static final String BASE_PRIMARY_TYPE = "baseType";
static final String MIXIN_TYPE_WITH_AUTO_PROP = "mixinTypeWithAutoCreatedProperty";
static final String MIXIN_TYPE_WITH_AUTO_CHILD = "mixinTypeWithAutoCreatedChildNode";
static final String PRIMARY_TYPE_A = "primaryTypeA";
static final String MIXIN_PROTECTED = "mixinProtected";
static final String PROPERTY_A = "propertyA";
static final String PROPERTY_B = "propertyB";
static final String PROPERTY_PROTECTED = "propertyProtected";
static final String CHILD_NODE_A = "nodeA";
static final String CHILD_NODE_B = "nodeB";
static final String CHILD_PROTECTED = "childProtected";
@Override
@Before
public void beforeEach() throws Exception {
super.beforeEach();
session.getWorkspace().getNodeTypeManager().registerNodeTypes(getTestTypes(), true);
}
@After
public void after() throws Exception {
if (session != null && session.isLive()) {
session.logout();
}
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowNullMixinTypeName() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.canAddMixin(null);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowEmptyMixinTypeName() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.canAddMixin("");
}
@Test( expected = NoSuchNodeTypeException.class )
public void shouldNotAllowInvalidMixinTypeName() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.canAddMixin("foo");
}
@Test
public void shouldNotAllowAddingMixinToProtectedNodes() throws Exception {
Node rootNode = session.getRootNode();
Node systemNode = rootNode.getNode("jcr:system");
assertThat(systemNode.getDefinition().isProtected(), is(true));
assertThat(systemNode.canAddMixin("mix:versionable"), is(false));
}
@Test
public void shouldAllowAddingMixinIfNoConflict() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A).addMixin("mix:referenceable");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_B), is(true));
}
@Test
public void shouldAllowAddingMixinIfPrimaryTypeConflicts() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A).addMixin("mix:referenceable");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_C), is(true));
}
@Test
public void shouldAllowAddingMixinIfMixinTypeConflicts() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A).addMixin(MIXIN_TYPE_B);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_C), is(true));
}
@Test
public void shouldAutoCreateAutoCreatedPropertiesOnAddition() throws Exception {
session.getRootNode().addNode("a");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_PROP), is(true));
nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_PROP);
Property prop = nodeA.getProperty(PROPERTY_B);
assertThat(prop, is(notNullValue()));
assertThat(prop.getLong(), is(10L));
}
@Test
public void shouldAutoCreateAutoCreatedChildNodesOnAddition() throws Exception {
session.getRootNode().addNode("a");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_CHILD), is(true));
nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_CHILD);
Node childNode = nodeA.getNode(CHILD_NODE_B);
assertThat(childNode, is(notNullValue()));
assertThat(childNode.getPrimaryNodeType().getName(), is("nt:unstructured"));
}
@Test( expected = ConstraintViolationException.class )
public void shouldNotAllowAdditionIfResidualPropertyConflicts() throws Exception {
session.getRootNode().addNode("a", "nt:unstructured");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
Property b = nodeA.setProperty(PROPERTY_B, "Not a boolean");
assertThat(b.getType(), is(not(PropertyType.UNDEFINED))); // see JavaDoc on javax.jcr.PropertyType.UNDEFINED
assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_PROP), is(false));
nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_PROP);
}
@Test
public void shouldAllowAdditionIfResidualPropertyDoesNotConflict() throws Exception {
session.getRootNode().addNode("a", "nt:unstructured");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.setProperty(PROPERTY_B, 10L);
assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_PROP), is(true));
nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_PROP);
}
@Test( expected = ConstraintViolationException.class )
public void shouldNotAllowAdditionIfResidualChildNodeConflicts() throws Exception {
session.getRootNode().addNode("a", "nt:unstructured").addNode(CHILD_NODE_B, "nt:base");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_CHILD), is(false));
nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_CHILD);
}
@Test
public void shouldAllowAdditionIfResidualChildNodeDoesNotConflict() throws Exception {
session.getRootNode().addNode("a", "nt:unstructured").addNode(CHILD_NODE_B, "nt:unstructured");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_CHILD), is(true));
nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_CHILD);
session.save();
Node newRootNode = session.getRootNode();
Node newNodeA = newRootNode.getNode("a");
Node newNodeB = newNodeA.getNode(CHILD_NODE_B);
assertThat(newNodeA.isNodeType(MIXIN_TYPE_WITH_AUTO_CHILD), is(true));
assertThat(newNodeB.isNodeType("nt:unstructured"), is(true));
assertThat(newNodeB, is(notNullValue()));
// Uncomment this to see the problem with the session cache not refreshing the immutable info for /a after a save
// assertThat(newNodeB.getDefinition().getDeclaringNodeType().getName(), is(MIXIN_TYPE_B));
}
@Test
public void shouldAllowSettingNewPropertyAfterAddingMixin() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A).addMixin("mix:referenceable");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_B), is(true));
nodeA.addMixin(MIXIN_TYPE_B);
nodeA.setProperty(PROPERTY_B, "some string");
session.save();
rootNode = session.getRootNode();
nodeA = rootNode.getNode("a");
Property propB = nodeA.getProperty(PROPERTY_B);
assertThat(propB, is(notNullValue()));
assertThat(propB.getValue().getString(), is("some string"));
}
@Test
public void shouldAllowAddingNewChildNodeAfterAddingMixin() throws Exception {
session.getRootNode().addNode("a", PRIMARY_TYPE_A).addMixin("mix:referenceable");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
assertThat(nodeA.canAddMixin(MIXIN_TYPE_B), is(true));
nodeA.addMixin(MIXIN_TYPE_B);
nodeA.addNode(CHILD_NODE_B);
session.save();
Node newRootNode = session.getRootNode();
Node newNodeA = newRootNode.getNode("a");
Node newNodeB = newNodeA.getNode(CHILD_NODE_B);
assertThat(newNodeB, is(notNullValue()));
assertThat(newNodeB.getDefinition().getDeclaringNodeType().getName(), is(MIXIN_TYPE_B));
}
@Test
public void shouldAllowRemovalIfNoConflict() throws Exception {
Node a = session.getRootNode().addNode("a");
a.addMixin(MIXIN_TYPE_B);
a.addNode(CHILD_NODE_B);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.removeMixin(MIXIN_TYPE_B);
session.save();
rootNode = session.getRootNode();
nodeA = rootNode.getNode("a");
assertThat(nodeA.getMixinNodeTypes().length, is(0));
}
@Test
public void shouldAllowRemovalIfExistingPropertyWouldHaveDefinition() throws Exception {
Node a = session.getRootNode().addNode("a", "nt:unstructured");
a.addMixin(MIXIN_TYPE_B);
a.setProperty(PROPERTY_B, true);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.removeMixin(MIXIN_TYPE_B);
session.save();
rootNode = session.getRootNode();
nodeA = rootNode.getNode("a");
assertThat(nodeA.getMixinNodeTypes().length, is(0));
}
@Test( expected = ConstraintViolationException.class )
public void shouldNotAllowRemovalIfExistingPropertyWouldHaveNoDefinition() throws Exception {
Node a = session.getRootNode().addNode("a", BASE_PRIMARY_TYPE);
a.addMixin(MIXIN_TYPE_B);
a.setProperty(PROPERTY_B, "true");
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.removeMixin(MIXIN_TYPE_B);
session.save();
}
@Test
public void shouldAllowRemovalIfExistingChildNodeWouldHaveDefinition() throws Exception {
Node a = session.getRootNode().addNode("a", "nt:unstructured");
a.addMixin(MIXIN_TYPE_B);
a.addNode(CHILD_NODE_B);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.removeMixin(MIXIN_TYPE_B);
}
@Test( expected = ConstraintViolationException.class )
public void shouldNotAllowRemovalIfExistingChildNodeWouldHaveNoDefinition() throws Exception {
Node a = session.getRootNode().addNode("a", BASE_PRIMARY_TYPE);
a.addMixin(MIXIN_TYPE_B);
a.addNode(CHILD_NODE_B);
session.save();
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
nodeA.removeMixin(MIXIN_TYPE_B);
}
@Test
@FixFor( "MODE-1912" )
public void shouldRemoveProtectedChildrenAndPropertiesWhenRemovingMixin() throws Exception {
Node protectedNode = session.getRootNode().addNode("protected", BASE_PRIMARY_TYPE);
protectedNode.addMixin(MIXIN_PROTECTED);
protectedNode.addNode(CHILD_PROTECTED);
protectedNode.setProperty(PROPERTY_PROTECTED, "a value");
session.save();
//change the item definitions to protected and run the validations
NodeTypeManager mgr = session.getWorkspace().getNodeTypeManager();
NodeTypeTemplate mixinProtected = createMixinProtected(mgr, true);
mgr.registerNodeType(mixinProtected, true);
String childPath = "/protected/" + CHILD_PROTECTED;
String propertyPath = "/protected/" + PROPERTY_PROTECTED;
protectedNode = session.getNode("/protected");
assertNotNull(session.getNode(childPath));
assertNotNull(session.getProperty(propertyPath));
protectedNode.removeMixin(MIXIN_PROTECTED);
session.save();
try {
session.getNode(childPath);
fail("Protected child should have been removed");
} catch (PathNotFoundException path) {
//expected
}
try {
session.getProperty(propertyPath);
fail("Protected property should have been removed");
} catch (PathNotFoundException path) {
//expected
}
}
@Test
@FixFor( "MODE-1949")
public void shouldNotAllowMixinRemovalIfPropertiesDefinedInParentMixinArePresent() throws Exception {
Node folder = session.getNode("/").addNode("folder", "nt:folder");
//add the publishArea mixin which inherits from mix:title
folder.addMixin("mode:publishArea");
folder.setProperty("jcr:title", "title");
folder.setProperty("jcr:description", "description");
session.save();
try {
folder.removeMixin("mode:publishArea");
session.save();
fail("The mixin should not be removed because there are still properties defined from the parent mixin");
} catch (ConstraintViolationException e) {
//expected
}
folder.setProperty("jcr:title", (Value)null);
session.save();
try {
folder.removeMixin("mode:publishArea");
session.save();
fail("The mixin should not be removed because there are still properties defined from the parent mixin");
} catch (ConstraintViolationException e) {
//expected
}
folder.setProperty("jcr:description", (Value)null);
session.save();
folder.removeMixin("mode:publishArea");
session.save();
}
protected NodeTypeDefinition[] getTestTypes() throws RepositoryException {
NodeTypeManager mgr = session.getWorkspace().getNodeTypeManager();
NodeTypeTemplate basePrimaryType = createBasePrimaryType(mgr);
NodeTypeTemplate mixinTypeA = createMixinA(mgr);
NodeTypeTemplate mixinTypeB = createMixinB(mgr);
NodeTypeTemplate mixinTypeC = createMixinC(mgr);
NodeTypeTemplate mixinTypeWithAutoChild = createMixinWithAutoChild(mgr);
NodeTypeTemplate mixinTypeWithAutoProperty = createMixinWithAutoProperty(mgr);
NodeTypeTemplate primaryTypeA = createPrimaryTypeA(mgr);
//create the items on mixin protected as "un-protected" first, so we can create children & properties
NodeTypeTemplate mixinProtected = createMixinProtected(mgr, false);
return new NodeTypeDefinition[] { basePrimaryType, mixinTypeA, mixinTypeB, mixinTypeC, mixinTypeWithAutoChild,
mixinTypeWithAutoProperty, primaryTypeA, mixinProtected};
}
private NodeTypeTemplate createBasePrimaryType( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate basePrimaryType = mgr.createNodeTypeTemplate();
basePrimaryType.setName(BASE_PRIMARY_TYPE);
return basePrimaryType;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createMixinWithAutoProperty( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate mixinTypeWithAutoProperty = mgr.createNodeTypeTemplate();
mixinTypeWithAutoProperty.setName("mixinTypeWithAutoCreatedProperty");
mixinTypeWithAutoProperty.setMixin(true);
PropertyDefinitionTemplate propertyB = mgr.createPropertyDefinitionTemplate();
propertyB.setName(PROPERTY_B);
propertyB.setMandatory(true);
propertyB.setAutoCreated(true);
propertyB.setOnParentVersion(OnParentVersionAction.IGNORE);
propertyB.setRequiredType(PropertyType.LONG);
propertyB.setDefaultValues(new Value[] {session.getValueFactory().createValue("10")});
mixinTypeWithAutoProperty.getPropertyDefinitionTemplates().add(propertyB);
return mixinTypeWithAutoProperty;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createMixinWithAutoChild( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate mixinTypeWithAutoChild = mgr.createNodeTypeTemplate();
mixinTypeWithAutoChild.setName("mixinTypeWithAutoCreatedChildNode");
mixinTypeWithAutoChild.setMixin(true);
NodeDefinitionTemplate childNodeB = mgr.createNodeDefinitionTemplate();
childNodeB.setName(CHILD_NODE_B);
childNodeB.setOnParentVersion(OnParentVersionAction.IGNORE);
childNodeB.setMandatory(true);
childNodeB.setAutoCreated(true);
childNodeB.setDefaultPrimaryTypeName("nt:unstructured");
childNodeB.setRequiredPrimaryTypeNames(new String[] {"nt:unstructured"});
mixinTypeWithAutoChild.getNodeDefinitionTemplates().add(childNodeB);
return mixinTypeWithAutoChild;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createPrimaryTypeA( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate primaryTypeA = mgr.createNodeTypeTemplate();
primaryTypeA.setName(PRIMARY_TYPE_A);
NodeDefinitionTemplate childNodeA = mgr.createNodeDefinitionTemplate();
childNodeA.setName(CHILD_NODE_A);
childNodeA.setOnParentVersion(OnParentVersionAction.IGNORE);
primaryTypeA.getNodeDefinitionTemplates().add(childNodeA);
PropertyDefinitionTemplate propertyA = mgr.createPropertyDefinitionTemplate();
propertyA.setName(PROPERTY_A);
propertyA.setOnParentVersion(OnParentVersionAction.IGNORE);
propertyA.setRequiredType(PropertyType.STRING);
primaryTypeA.getPropertyDefinitionTemplates().add(propertyA);
return primaryTypeA;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createMixinC( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate mixinTypeC = mgr.createNodeTypeTemplate();
mixinTypeC.setName(MIXIN_TYPE_C);
mixinTypeC.setMixin(true);
PropertyDefinitionTemplate propertyB = mgr.createPropertyDefinitionTemplate();
propertyB.setName(PROPERTY_B);
propertyB.setOnParentVersion(OnParentVersionAction.IGNORE);
propertyB.setRequiredType(PropertyType.STRING);
mixinTypeC.getPropertyDefinitionTemplates().add(propertyB);
return mixinTypeC;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createMixinB( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate mixinTypeB = mgr.createNodeTypeTemplate();
mixinTypeB.setName(MIXIN_TYPE_B);
mixinTypeB.setMixin(true);
NodeDefinitionTemplate childNodeB = mgr.createNodeDefinitionTemplate();
childNodeB.setName(CHILD_NODE_B);
childNodeB.setDefaultPrimaryTypeName("nt:base");
childNodeB.setOnParentVersion(OnParentVersionAction.IGNORE);
mixinTypeB.getNodeDefinitionTemplates().add(childNodeB);
PropertyDefinitionTemplate propertyB = mgr.createPropertyDefinitionTemplate();
propertyB.setName(PROPERTY_B);
propertyB.setOnParentVersion(OnParentVersionAction.IGNORE);
propertyB.setRequiredType(PropertyType.BINARY);
mixinTypeB.getPropertyDefinitionTemplates().add(propertyB);
NodeDefinitionTemplate childNodeA = mgr.createNodeDefinitionTemplate();
childNodeA.setName(CHILD_NODE_A);
childNodeA.setOnParentVersion(OnParentVersionAction.IGNORE);
mixinTypeB.getNodeDefinitionTemplates().add(childNodeA);
return mixinTypeB;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createMixinProtected( NodeTypeManager mgr, boolean makeItemsProtected ) throws RepositoryException {
NodeTypeTemplate mixinProtected = mgr.createNodeTypeTemplate();
mixinProtected.setName(MIXIN_PROTECTED);
mixinProtected.setMixin(true);
NodeDefinitionTemplate childProtected = mgr.createNodeDefinitionTemplate();
childProtected.setName(CHILD_PROTECTED);
childProtected.setProtected(makeItemsProtected);
childProtected.setDefaultPrimaryTypeName("nt:base");
childProtected.setOnParentVersion(OnParentVersionAction.IGNORE);
mixinProtected.getNodeDefinitionTemplates().add(childProtected);
PropertyDefinitionTemplate propertyProtected = mgr.createPropertyDefinitionTemplate();
propertyProtected.setProtected(makeItemsProtected);
propertyProtected.setName(PROPERTY_PROTECTED);
propertyProtected.setOnParentVersion(OnParentVersionAction.IGNORE);
propertyProtected.setRequiredType(PropertyType.STRING);
mixinProtected.getPropertyDefinitionTemplates().add(propertyProtected);
return mixinProtected;
}
@SuppressWarnings( {"unchecked"} )
private NodeTypeTemplate createMixinA( NodeTypeManager mgr ) throws RepositoryException {
NodeTypeTemplate mixinTypeA = mgr.createNodeTypeTemplate();
mixinTypeA.setName(MIXIN_TYPE_A);
mixinTypeA.setMixin(true);
NodeDefinitionTemplate childNodeA = mgr.createNodeDefinitionTemplate();
childNodeA.setName(CHILD_NODE_A);
childNodeA.setOnParentVersion(OnParentVersionAction.IGNORE);
mixinTypeA.getNodeDefinitionTemplates().add(childNodeA);
PropertyDefinitionTemplate propertyA = mgr.createPropertyDefinitionTemplate();
propertyA.setName(PROPERTY_A);
propertyA.setOnParentVersion(OnParentVersionAction.IGNORE);
propertyA.setRequiredType(PropertyType.STRING);
mixinTypeA.getPropertyDefinitionTemplates().add(propertyA);
return mixinTypeA;
}
}