/* * Copyright 2013 eXo Platform SAS * * 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 juzu.impl.metamodel; import juzu.impl.common.CycleDetectionException; import juzu.test.AbstractTestCase; import org.junit.Test; import java.util.Arrays; import java.util.LinkedList; /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */ public class MetaModelTestCase extends AbstractTestCase { /** . */ private static final Key<MetaModelObject> A = Key.of("a", MetaModelObject.class); /** . */ private static final Key<MetaModelObject> B = Key.of("b", MetaModelObject.class); /** . */ private static final Key<MetaModelObject> C = Key.of("c", MetaModelObject.class); /** . */ private static final Key<MetaModelObject> D = Key.of("d", MetaModelObject.class); /** . */ private Context context; @Override public void setUp() throws Exception { this.context = new Context(); } @Test public void testCannotRemoveRoot() { Simple a = context.create("a"); Simple b = context.create("b"); a.addChild(B, b); // a.remove(); assertSame(b, a.getChild(B)); context.assertEmpty(); } @Test public void testTransitiveRemove() { Simple a = context.create("a"); Simple b = context.create("b"); Simple c = context.create("c"); a.addChild(B, b).addChild(C, c); // b.remove(); context.assertPreDetach("c"); context.assertRemove("c"); context.assertPreDetach("b"); context.assertRemove("b"); context.assertEmpty(); } @Test public void testTransitiveRemoveChild() { Simple a = context.create("a"); Simple b = context.create("b"); Simple c = context.create("c"); a.addChild(B, b).addChild(C, c); // a.removeChild(B); context.assertPreDetach("c"); context.assertRemove("c"); context.assertPreDetach("b"); context.assertRemove("b"); context.assertEmpty(); } @Test public void testRemoveOrphan() { Simple a = context.create("a"); Simple b = context.create("b"); Simple c = context.create("c"); a.addChild(C, c); b.addChild(C, c); // a.removeChild(C); context.assertPreDetach("c"); context.assertEmpty(); b.removeChild(C); context.assertPreDetach("c"); context.assertRemove("c"); context.assertEmpty(); } @Test public void testBug() { Simple a = context.create("a"); Simple b = context.create("b"); Simple c = context.create("c"); Simple d = context.create("d"); a.addChild(C, c); b.addChild(C, c); c.addChild(D, d); // assertSame(c, a.removeChild(C)); assertNull(a.getChild(C)); assertSame(c, b.getChild(C)); assertSame(d, c.getChild(D)); } @Test public void testEventWhenRemoved() { Simple a = context.create("a"); Simple b = context.create("b"); a.addChild(B, b); } @Test public void testCycleDetection() { Simple a = context.create("a"); Simple b = context.create("b"); Simple c = context.create("c"); a.addChild(B, b); b.addChild(C, c); try { c.addChild(A, a); fail("Was expecting cycle detection"); } catch (CycleDetectionException ok) { assertEquals(Arrays.asList(a, b, c), ok.getPath()); } } @Test public void testSelfCycleDetection() { Simple a = context.create("a"); try { a.addChild(A, a); fail("Was expecting cycle detection"); } catch (CycleDetectionException ok) { assertEquals(Arrays.asList(a), ok.getPath()); } } static class Simple extends MetaModelObject { /** . */ final Context context; /** . */ final String name; Simple(Context context, String name) { this.context = context; this.name = name; } @Override protected void preDetach(MetaModelObject parent) { context.addLast(new Event(this, Event.PRE_DETACH)); } @Override protected void preRemove() { context.addLast(new Event(this, Event.REMOVED)); } @Override public String toString() { return "Simple[" + name + "]"; } } static class Event { /** . */ static final int ADDED = 0; /** . */ static final int REMOVED = 1; /** . */ static final int PRE_DETACH = 2; /** . */ private final Simple source; /** . */ private final int kind; Event(Simple source, int kind) { this.source = source; this.kind = kind; } } static class Context extends LinkedList<Event> { Simple create(String name) { return new Simple(this, name); } void assertRemove(String name) { assertTrue("Expecting to have at least one event", size() > 0); Event event = removeFirst(); assertEquals(Event.REMOVED, event.kind); assertEquals(name, event.source.name); } void assertPreDetach(String name) { assertTrue("Expecting to have at least one event", size() > 0); Event event = removeFirst(); assertEquals(Event.PRE_DETACH, event.kind); assertEquals(name, event.source.name); } void assertEmpty() { assertTrue(isEmpty()); } } }