Index: modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (revision 1888) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (working copy) @@ -698,6 +698,57 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node return new JcrPropertyIterator(references); } + @Override + public PropertyIterator getWeakReferences() throws RepositoryException { + return getWeakReferences(null); + } + + @Override + public PropertyIterator getWeakReferences( String propertyName ) throws RepositoryException { + checkSession(); + if (!this.isReferenceable()) { + // This node is not referenceable, so it cannot have any references to it ... + return new JcrEmptyPropertyIterator(); + } + NodeIterator iter = referencingNodes(Integer.MAX_VALUE); + if (!iter.hasNext()) { + return new JcrEmptyPropertyIterator(); + } + String uuid = getUUID(); + List references = new LinkedList(); + while (iter.hasNext()) { + javax.jcr.Node node = iter.nextNode(); + + // Go through the properties and look for reference properties that have a value of this node's UUID ... + PropertyIterator propIter = node.getProperties(); + while (propIter.hasNext()) { + Property prop = propIter.nextProperty(); + // Look at the definition's required type ... + int propType = prop.getDefinition().getRequiredType(); + if (propType == PropertyType.WEAKREFERENCE || propType == PropertyType.UNDEFINED + || propType == PropertyType.STRING) { + if (propertyName != null && !propertyName.equals(prop.getName())) continue; + if (prop.getDefinition().isMultiple()) { + for (Value value : prop.getValues()) { + if (uuid.equals(value.getString())) { + references.add(prop); + break; + } + } + } else { + Value value = prop.getValue(); + if (uuid.equals(value.getString())) { + references.add(prop); + } + } + } + } + } + + if (references.isEmpty()) return new JcrEmptyPropertyIterator(); + return new JcrPropertyIterator(references); + } + /** * A non-standard method to obtain a property given the {@link Name ModeShape Name} object. This method is faster * @@ -988,9 +1039,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node return false; } - NodeType primaryType = this.getPrimaryNodeType(); - NodeType[] mixinTypes = this.getMixinNodeTypes(); - if (mixinCandidateType.isAbstract()) { return false; } @@ -999,11 +1047,7 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node return false; } - /* MODE FLAG - Needs to be uncommented for JCR 2 */ - // if (isNodeType(mixinCandidateType.getInternalName())) return true; - if (mixinCandidateType.conflictsWith(primaryType, mixinTypes)) { - return false; - } + if (isNodeType(mixinCandidateType.getInternalName())) return true; // ------------------------------------------------------------------------------ // Check for any existing properties based on residual definitions that conflict @@ -2229,18 +2273,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node } @Override - public PropertyIterator getWeakReferences() throws RepositoryException { - // TODO Auto-generated method stub - return null; - } - - @Override - public PropertyIterator getWeakReferences( String name ) throws RepositoryException { - // TODO Auto-generated method stub - return null; - } - - @Override public void removeShare() throws VersionException, LockException, ConstraintViolationException, RepositoryException { // TODO Auto-generated method stub Index: modeshape-jcr/src/test/java/org/modeshape/jcr/JcrTckTest.java =================================================================== --- modeshape-jcr/src/test/java/org/modeshape/jcr/JcrTckTest.java (revision 1888) +++ modeshape-jcr/src/test/java/org/modeshape/jcr/JcrTckTest.java (working copy) @@ -35,13 +35,17 @@ import org.apache.jackrabbit.test.api.DocumentViewImportTest; import org.apache.jackrabbit.test.api.DoublePropertyTest; import org.apache.jackrabbit.test.api.ExportDocViewTest; import org.apache.jackrabbit.test.api.ExportSysViewTest; +import org.apache.jackrabbit.test.api.GetWeakReferencesTest; import org.apache.jackrabbit.test.api.HasPermissionTest; import org.apache.jackrabbit.test.api.ImpersonateTest; import org.apache.jackrabbit.test.api.LifecycleTest; import org.apache.jackrabbit.test.api.LongPropertyTest; import org.apache.jackrabbit.test.api.NamePropertyTest; +import org.apache.jackrabbit.test.api.NameTest; import org.apache.jackrabbit.test.api.NamespaceRegistryReadMethodsTest; import org.apache.jackrabbit.test.api.NamespaceRegistryTest; +import org.apache.jackrabbit.test.api.NodeAddMixinTest; +import org.apache.jackrabbit.test.api.NodeCanAddMixinTest; import org.apache.jackrabbit.test.api.NodeDiscoveringNodeTypesTest; import org.apache.jackrabbit.test.api.NodeItemIsModifiedTest; import org.apache.jackrabbit.test.api.NodeItemIsNewTest; @@ -253,8 +257,6 @@ public class JcrTckTest { suite.addTestSuite(ExportSysViewTest.class); suite.addTestSuite(ExportDocViewTest.class); - // This test can't be verified on the the FS Connector or the JDCB Metadata Connector. - // suite.addTestSuite(NameTest.class); // suite.addTestSuite(PathTest.class); // The tests in this suite are level one @@ -335,12 +337,15 @@ public class JcrTckTest { suite.addTestSuite(PropertyItemIsModifiedTest.class); suite.addTestSuite(PropertyItemIsNewTest.class); - // suite.addTestSuite(NodeAddMixinTest.class); - // suite.addTestSuite(NodeCanAddMixinTest.class); + suite.addTestSuite(NodeAddMixinTest.class); + suite.addTestSuite(NodeCanAddMixinTest.class); suite.addTestSuite(NodeRemoveMixinTest.class); suite.addTestSuite(NodeSetPrimaryTypeTest.class); + // This isn't marked as read-only, so it causes problems if you put it with the L1 tests + suite.addTestSuite(NameTest.class); + suite.addTestSuite(WorkspaceCloneReferenceableTest.class); suite.addTestSuite(WorkspaceCloneSameNameSibsTest.class); suite.addTestSuite(WorkspaceCloneTest.class); @@ -371,7 +376,7 @@ public class JcrTckTest { suite.addTestSuite(NodeTypeCreationTest.class); // // new node types - // suite.addTestSuite(GetWeakReferencesTest.class); + suite.addTestSuite(GetWeakReferencesTest.class); // // new Session features suite.addTestSuite(SessionRemoveItemTest.class); Index: modeshape-jcr/src/test/java/org/modeshape/jcr/MixinTest.java =================================================================== --- modeshape-jcr/src/test/java/org/modeshape/jcr/MixinTest.java (revision 1888) +++ modeshape-jcr/src/test/java/org/modeshape/jcr/MixinTest.java (working copy) @@ -137,7 +137,7 @@ public class MixinTest extends AbstractSessionTest { } @Test - public void shouldNotAllowAddingMixinIfPrimaryTypeConflicts() throws Exception { + public void shouldAllowAddingMixinIfPrimaryTypeConflicts() throws Exception { graph.create("/a").and(); graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A); graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(JcrMixLexicon.REFERENCEABLE.getString(registry)); @@ -145,11 +145,11 @@ public class MixinTest extends AbstractSessionTest { Node rootNode = session.getRootNode(); Node nodeA = rootNode.getNode("a"); - assertThat(nodeA.canAddMixin(MIXIN_TYPE_C.getString(registry)), is(false)); + assertThat(nodeA.canAddMixin(MIXIN_TYPE_C.getString(registry)), is(true)); } @Test - public void shouldNotAllowAddingMixinIfMixinTypeConflicts() throws Exception { + public void shouldAllowAddingMixinIfMixinTypeConflicts() throws Exception { graph.create("/a").and(); graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.BASE.getString(registry)); graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B); @@ -157,7 +157,7 @@ public class MixinTest extends AbstractSessionTest { Node rootNode = session.getRootNode(); Node nodeA = rootNode.getNode("a"); - assertThat(nodeA.canAddMixin(MIXIN_TYPE_C.getString(registry)), is(false)); + assertThat(nodeA.canAddMixin(MIXIN_TYPE_C.getString(registry)), is(true)); } @Test