/* * Copyright (C) 2009 eXo Platform SAS. * * This 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 2.1 of * the License, or (at your option) any later version. * * This software 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 this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.api.writing; import org.exoplatform.services.jcr.JcrAPIBaseTest; import org.exoplatform.services.jcr.impl.core.NodeImpl; import java.io.ByteArrayInputStream; import java.util.Calendar; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.PropertyType; import javax.jcr.ReferentialIntegrityException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; import javax.jcr.ValueFactory; /** * Created by The eXo Platform SAS. * * @author <a href="mailto:geaz@users.sourceforge.net">Gennady Azarenkov</a> * @version $Id: TestNodeReference.java 11907 2008-03-13 15:36:21Z ksm $ */ public class TestNodeReference extends JcrAPIBaseTest { public void testGetReferences() throws RepositoryException { Node root = session.getRootNode(); Node testNode = root.addNode("testGetReferences", "nt:unstructured"); Node testNode1 = root.addNode("testGetReferences1", "nt:unstructured"); testNode.addMixin("mix:referenceable"); testNode1.addMixin("mix:referenceable"); // Should be saved first root.save(); Node n1 = root.addNode("n1", "nt:unstructured"); Node n2 = root.addNode("n2", "nt:unstructured"); Node n11 = root.addNode("n11", "nt:unstructured"); n1.setProperty("p1", new String[]{((NodeImpl)testNode).getInternalIdentifier(), ((NodeImpl)testNode1).getInternalIdentifier()}, PropertyType.REFERENCE); // n1.setProperty("p1", testNode); // n2.setProperty("p1", testNode); // n11.setProperty("p1", testNode1); root.save(); PropertyIterator refs = testNode.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { log.debug("ref >>>" + refs.nextProperty()); } } assertEquals(1, testNode.getReferences().getSize()); assertEquals(1, testNode1.getReferences().getSize()); testNode.remove(); try { root.save(); fail("ReferentialIntegrityException"); } catch (ReferentialIntegrityException e) { } } public void testGetReferences2() throws RepositoryException { Node root = session.getRootNode(); Node testNode = root.addNode("testGetReferences", "nt:unstructured"); Node testNode1 = root.addNode("testGetReferences1", "nt:unstructured"); Node testNode2 = root.addNode("testGetReferences2", "nt:unstructured"); Node n1 = root.addNode("n1", "nt:unstructured"); Node n2 = root.addNode("n2", "nt:unstructured"); Node n3 = root.addNode("n3", "nt:unstructured"); Node n4 = root.addNode("n4", "nt:unstructured"); try { testNode.addMixin("mix:referenceable"); testNode1.addMixin("mix:referenceable"); root.save(); testNode2.addMixin("mix:versionable"); // Should be saved first root.save(); // version stuff testNode2.checkin(); testNode2.checkout(); testNode2.addNode("Any node").setProperty("Any prop", true); root.save(); testNode2.checkin(); testNode2.checkout(); n1.setProperty("p1", testNode); n2.setProperty("p1", testNode1); n3.setProperty("p1", testNode2); n3.setProperty("p0", testNode); n3.setProperty("p1", testNode1); // !!! instead testNode2 n3.setProperty("p2", testNode2); ValueFactory vFactory = n2.getSession().getValueFactory(); n2.setProperty("p2_multiple", new Value[]{vFactory.createValue(testNode), vFactory.createValue(testNode1), vFactory.createValue(testNode2)}); n4.setProperty("p1_multiple", new Value[]{vFactory.createValue(testNode1), vFactory.createValue(testNode1), vFactory.createValue(testNode)}); // i.e. REFERENCEs // n1/p1 -> testNode // n2/p1 -> testNode1 // n3/p0 -> testNode // n3/p1 -> testNode1 // n3/p2 -> testNode2 // n2/p2_multiple -> testNode, testNode1, testNode2 // n4/p1_multiple -> testNode1, testNode1, testNode root.save(); PropertyIterator refs = testNode.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { Property p = refs.nextProperty(); log.debug(testNode.getPath() + " ref >>> " + p.getPath()); } } assertEquals(4, testNode.getReferences().getSize()); refs = testNode1.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { Property p = refs.nextProperty(); log.debug(testNode1.getPath() + " ref >>> " + p.getPath()); } } assertEquals(5, testNode1.getReferences().getSize()); refs = testNode2.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { Property p = refs.nextProperty(); log.debug(testNode2.getPath() + " ref >>> " + p.getPath()); } } assertEquals(2, testNode2.getReferences().getSize()); testNode.remove(); try { root.save(); fail("ReferentialIntegrityException must be"); } catch (ReferentialIntegrityException e) { root.refresh(false); // rollback remove in session (7.1.1.7 Item) } testNode1.remove(); try { root.save(); fail("ReferentialIntegrityException must be"); } catch (ReferentialIntegrityException e) { root.refresh(false); // rollback remove in session (7.1.1.7 Item) } testNode2.remove(); try { root.save(); fail("ReferentialIntegrityException must be"); } catch (ReferentialIntegrityException e) { root.refresh(false); // rollback remove in session (7.1.1.7 Item) } // remove some props n1.getProperty("p1").remove(); n3.getProperty("p0").remove(); n2.setProperty("p2_multiple", new Value[]{vFactory.createValue(testNode1), vFactory.createValue(testNode2)}); n4.setProperty("p1_multiple", new Value[]{vFactory.createValue(testNode1), vFactory.createValue(testNode1)}); // i.e. REFERENCEs // ....n1/p1 -> testNode (Removed) // n2/p1 -> testNode1 // ....n3/p0 -> testNode (Removed) // n3/p1 -> testNode1 // n3/p2 -> testNode2 // n2/p2_multiple -> ....testNode (Removed), testNode1, testNode2 // n4/p1_multiple -> testNode1, testNode1, ....testNode (Removed) root.save(); refs = testNode.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { Property p = refs.nextProperty(); log.debug(testNode.getPath() + " ref >>> " + p.getPath()); } } assertEquals(0, testNode.getReferences().getSize()); refs = testNode1.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { Property p = refs.nextProperty(); log.debug(testNode1.getPath() + " ref >>> " + p.getPath()); } } assertEquals(5, testNode1.getReferences().getSize()); refs = testNode2.getReferences(); if (log.isDebugEnabled()) { while (refs.hasNext()) { Property p = refs.nextProperty(); log.debug(testNode2.getPath() + " ref >>> " + p.getPath()); } } assertEquals(2, testNode2.getReferences().getSize()); testNode.remove(); try { root.save(); } catch (ReferentialIntegrityException e) { fail("ReferentialIntegrityException must has no place here"); } testNode1.remove(); try { root.save(); fail("ReferentialIntegrityException must be"); } catch (ReferentialIntegrityException e) { } testNode2.remove(); try { root.save(); fail("ReferentialIntegrityException must be"); } catch (ReferentialIntegrityException e) { } } catch (Exception e) { e.printStackTrace(); fail("An exception occurs. " + e.getMessage()); } finally { // finalization n2.getProperty("p1").remove(); n3.getProperty("p1").remove(); n3.getProperty("p2").remove(); n2.getProperty("p2_multiple").remove(); n4.getProperty("p1_multiple").remove(); root.save(); } } public void testGetRegerencesOnChangedNode() throws Exception { Node testNode = root.addNode("testGetReferences", "nt:unstructured"); Node refNode = root.addNode("refNode", "nt:unstructured"); assertTrue(testNode.canAddMixin("mix:referenceable")); testNode.addMixin("mix:referenceable"); refNode.setProperty("p", refNode.getSession().getValueFactory().createValue(testNode)); session.save(); // change node assertTrue(testNode.canAddMixin("mix:lockable")); testNode.addMixin("mix:lockable"); PropertyIterator refs = testNode.getReferences(); assertEquals(1, refs.getSize()); } public void testGetTransientDeletedReferences() throws Exception { Node file = root.addNode("n", "nt:file"); Node content = file.addNode("jcr:content", "nt:resource"); content.setProperty("jcr:data", new ByteArrayInputStream(new byte[0])); content.setProperty("jcr:mimeType", ""); content.setProperty("jcr:lastModified", Calendar.getInstance()); root.save(); Node link = root.addNode("link", "nt:linkedFile"); link.setProperty("jcr:content", content); root.save(); // remove linked file but don't save it content.getReferences().nextProperty().getParent().remove(); try { PropertyIterator it = content.getReferences(); assertEquals(0, it.getSize()); root.refresh(false); it = content.getReferences(); assertEquals(1, it.getSize()); } catch (Exception e) { fail(e.getMessage()); } } public void testGetTransientDeletedReferences_AnotherSession() throws Exception { Node file = root.addNode("n", "nt:file"); Node content = file.addNode("jcr:content", "nt:resource"); content.setProperty("jcr:data", new ByteArrayInputStream(new byte[0])); content.setProperty("jcr:mimeType", ""); content.setProperty("jcr:lastModified", Calendar.getInstance()); root.save(); Node link = root.addNode("link", "nt:linkedFile"); link.setProperty("jcr:content", content); root.save(); // remove linked file but don't save it content.getReferences().nextProperty().getParent().remove(); Session anotherSession = repository.login(credentials, root.getSession().getWorkspace().getName()); try { // but another session still see the link as a reference PropertyIterator it = ((Node)anotherSession.getItem(content.getPath())).getReferences(); assertEquals(1, it.getSize()); } catch (Exception e) { fail(e.getMessage()); } finally { anotherSession.logout(); } } public void testGetDeletedReferences() throws Exception { Node file = root.addNode("n", "nt:file"); Node content = file.addNode("jcr:content", "nt:resource"); content.setProperty("jcr:data", new ByteArrayInputStream(new byte[0])); content.setProperty("jcr:mimeType", ""); content.setProperty("jcr:lastModified", Calendar.getInstance()); root.save(); Node link = root.addNode("link", "nt:linkedFile"); link.setProperty("jcr:content", content); root.save(); // remove linked file but and save it content.getReferences().nextProperty().getParent().remove(); root.save(); try { PropertyIterator it = content.getReferences(); assertEquals(0, it.getSize()); } catch (Exception e) { fail(e.getMessage()); } } }