Commits

Michael Ludwig committed 98b9f23

Allow component definitions to extend from non-Component interfaces

Comments (0)

Files changed (8)

src/main/java/com/lhkbob/entreri/Component.java

  * method that defines the property. They are ignored if added to the setter method. The getter method is
  * considered to be the definition of the property and the setter is only specified to complete the API.
  * <p/>
+ * As interfaces, Component definitions can extend from other interfaces. However, any methods defined in the
+ * additional super-interfaces must follow the exact same property specification. The total sum of methods not
+ * defined by Component, Owner, Ownable, or Object must produce a valid property specification. These
+ * super-interfaces do not need to extend Component themselves, indeed it is recommended that they do not
+ * otherwise it would be possible for entities to have the sub-component and super-component expressed at the
+ * same time.
+ * <p/>
  * The generated proxies will implement equals() and hashCode() based on their type and the id of their owning
  * entity. The {@link ComponentIterator} class creates flyweight component instances whose identity changes as
  * iteration proceeds; equals() and hashCode() will behave appropriately. This means that flyweight components

src/main/java/com/lhkbob/entreri/impl/MirrorComponentSpecification.java

                 continue;
             }
 
-            if (!tu.isAssignable(declare, baseComponentType)) {
-                throw fail(declare, name + ", method is not declared in Component");
-            }
-
             if (name.startsWith("is")) {
                 processGetter(m, "is", getters);
             } else if (name.startsWith("has")) {

src/main/java/com/lhkbob/entreri/impl/ReflectionComponentSpecification.java

                 continue;
             }
 
-            if (!Component.class.isAssignableFrom(method.getDeclaringClass())) {
-                throw fail(md, method + ", method is not declared by a component");
-            }
-
             if (method.getName().startsWith("is")) {
                 processGetter(method, "is", getters);
             } else if (method.getName().startsWith("has")) {

src/test/java/com/lhkbob/entreri/ComponentTest.java

  */
 package com.lhkbob.entreri;
 
-import com.lhkbob.entreri.components.*;
-import com.lhkbob.entreri.property.EnumProperty;
+import com.lhkbob.entreri.components.ComplexComponent;
+import com.lhkbob.entreri.components.CustomProperty;
+import com.lhkbob.entreri.components.FloatPropertyFactory;
+import com.lhkbob.entreri.components.IntComponent;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.lang.reflect.Field;
-
 public class ComponentTest {
     @Test
     public void testIsAliveComponentRemove() {
         c1.setParams((short) 4, (short) 5);
         c1.setFloat(2.0f);
         c1.setInt(140);
+        c1.setSuperValue(12);
+        c1.setEnum(ComplexComponent.TestEnum.V2);
 
         Assert.assertEquals(19, c1.hasBletch().value);
         Assert.assertEquals(23.2f, c1.getFactoryFloat(), 0.00001f);
         Assert.assertEquals((short) 5, c1.getParam2());
         Assert.assertEquals(2.0f, c1.getFloat(), 0.00001f);
         Assert.assertEquals(140, c1.getInt());
+        Assert.assertEquals(12, c1.getSuperValue());
+        Assert.assertEquals(ComplexComponent.TestEnum.V2, c1.getEnum());
 
         // add a second component and make sure things didn't get goofed up
         Entity e2 = system.addEntity();
         Assert.assertEquals((short) 0, c2.getParam2());
         Assert.assertEquals(0f, c2.getFloat(), 0.00001f);
         Assert.assertEquals(0, c2.getInt());
-    }
-
-    @Test
-    public void testGenericEnumProperty() throws Exception {
-        EntitySystem system = EntitySystem.Factory.create();
-        EnumComponent en = system.addEntity().add(EnumComponent.class);
-
-        // use reflection to verify that it picked an EnumProperty
-        Field prop = en.getClass().getDeclaredField("property0");
-        prop.setAccessible(true);
-        Assert.assertEquals(EnumProperty.class, prop.getType());
-        EnumProperty data = (EnumProperty) prop.get(en);
-
-        Assert.assertEquals(EnumComponent.TestEnum.V1, en.getValue());
-        en.setValue(EnumComponent.TestEnum.V2);
-        Assert.assertEquals(1, data.getIndexedData()[en.getIndex()]);
+        Assert.assertEquals(0, c2.getSuperValue());
+        Assert.assertEquals(ComplexComponent.TestEnum.V1, c2.getEnum());
     }
 
     @Test

src/test/java/com/lhkbob/entreri/components/ComplexComponent.java

  *
  * @author Michael Ludwig
  */
-public interface ComplexComponent extends IntComponent, FloatComponent {
+public interface ComplexComponent extends IntComponent, FloatComponent, SuperInterface {
+    public static enum TestEnum {
+        V1,
+        V2
+    }
+
+    public TestEnum getEnum();
+
+    public void setEnum(TestEnum e);
+
     public void setLong(long i);
 
     @DefaultLong(Long.MAX_VALUE)

src/test/java/com/lhkbob/entreri/components/EnumComponent.java

-package com.lhkbob.entreri.components;
-
-import com.lhkbob.entreri.Component;
-
-/**
- *
- */
-public interface EnumComponent extends Component {
-    public static enum TestEnum {
-        V1,
-        V2
-    }
-
-    public TestEnum getValue();
-
-    public EnumComponent setValue(TestEnum value);
-}

src/test/java/com/lhkbob/entreri/components/SuperInterface.java

+package com.lhkbob.entreri.components;
+
+/**
+ *
+ */
+public interface SuperInterface {
+    public int getSuperValue();
+
+    public void setSuperValue(int value);
+}

src/test/java/com/lhkbob/entreri/impl/ComponentSpecificationTest.java

         }
 
         // verify that properties are mapped properly
-
         // property - int from IntComponent
-        PropertyDeclaration intSpec = props.get("int");
+        PropertyDeclaration intSpec = props.remove("int");
         Assert.assertNotNull(intSpec);
         Assert.assertFalse(intSpec.isShared());
+        Assert.assertFalse(intSpec.isPropertyGeneric());
         IntProperty intProp = (IntProperty) intSpec.getPropertyFactory().create();
         ((IntProperty.Factory) intSpec.getPropertyFactory()).setDefaultValue(intProp, 0);
         Assert.assertEquals(0, intProp.get(0));
         Assert.assertEquals(0, intSpec.getSetterParameter());
 
         // property - float from FloatComponent
-        PropertyDeclaration floatSpec = props.get("float");
+        PropertyDeclaration floatSpec = props.remove("float");
         Assert.assertNotNull(floatSpec);
         Assert.assertFalse(floatSpec.isShared());
+        Assert.assertFalse(floatSpec.isPropertyGeneric());
         FloatProperty floatProp = (FloatProperty) floatSpec.getPropertyFactory().create();
         ((FloatProperty.Factory) floatSpec.getPropertyFactory()).setDefaultValue(floatProp, 0);
         Assert.assertEquals(0f, floatProp.get(0), 0.0001f);
         Assert.assertEquals(0, floatSpec.getSetterParameter());
 
         // property - long
-        PropertyDeclaration longSpec = props.get("long");
+        PropertyDeclaration longSpec = props.remove("long");
         Assert.assertNotNull(longSpec);
         Assert.assertFalse(longSpec.isShared());
+        Assert.assertFalse(longSpec.isPropertyGeneric());
         LongProperty longProp = (LongProperty) longSpec.getPropertyFactory().create();
         ((LongProperty.Factory) longSpec.getPropertyFactory()).setDefaultValue(longProp, 0);
         Assert.assertEquals(Long.MAX_VALUE, longProp.get(0));
         Assert.assertEquals(0, longSpec.getSetterParameter());
 
         // property - factoryFloat
-        PropertyDeclaration facFloatSpec = props.get("factoryFloat");
+        PropertyDeclaration facFloatSpec = props.remove("factoryFloat");
         Assert.assertNotNull(facFloatSpec);
         Assert.assertFalse(facFloatSpec.isShared());
+        Assert.assertFalse(facFloatSpec.isPropertyGeneric());
         FloatProperty floatFactoryProp = (FloatProperty) facFloatSpec.getPropertyFactory().create();
         ((FloatPropertyFactory) facFloatSpec.getPropertyFactory()).setDefaultValue(floatFactoryProp, 0);
         Assert.assertEquals(FloatPropertyFactory.DEFAULT, floatFactoryProp.get(0), 0.0001f);
         Assert.assertEquals(0, facFloatSpec.getSetterParameter());
 
         // property - param1
-        PropertyDeclaration param1Spec = props.get("param1");
+        PropertyDeclaration param1Spec = props.remove("param1");
         Assert.assertNotNull(param1Spec);
         Assert.assertFalse(param1Spec.isShared());
+        Assert.assertFalse(param1Spec.isPropertyGeneric());
         ShortProperty param1Prop = (ShortProperty) param1Spec.getPropertyFactory().create();
         ((ShortProperty.Factory) param1Spec.getPropertyFactory()).setDefaultValue(param1Prop, 0);
         Assert.assertEquals((short) 0, param1Prop.get(0));
         Assert.assertEquals(0, param1Spec.getSetterParameter());
 
         // property - param2
-        PropertyDeclaration param2Spec = props.get("param2");
+        PropertyDeclaration param2Spec = props.remove("param2");
         Assert.assertNotNull(param2Spec);
         Assert.assertFalse(param2Spec.isShared());
+        Assert.assertFalse(param2Spec.isPropertyGeneric());
         ShortProperty param2Prop = (ShortProperty) param2Spec.getPropertyFactory().create();
         ((ShortProperty.Factory) param2Spec.getPropertyFactory()).setDefaultValue(param2Prop, 0);
         Assert.assertEquals((short) 0, param2Prop.get(0));
         Assert.assertEquals(1, param2Spec.getSetterParameter());
 
         // property - foo-blah
-        PropertyDeclaration fooblahSpec = props.get("foo-blah");
+        PropertyDeclaration fooblahSpec = props.remove("foo-blah");
         Assert.assertNotNull(fooblahSpec);
         Assert.assertFalse(fooblahSpec.isShared());
+        Assert.assertFalse(fooblahSpec.isPropertyGeneric());
         BooleanProperty fooblahProp = (BooleanProperty) fooblahSpec.getPropertyFactory().create();
         ((BooleanProperty.Factory) fooblahSpec.getPropertyFactory()).setDefaultValue(fooblahProp, 0);
         Assert.assertEquals(false, fooblahProp.get(0));
         Assert.assertEquals(0, fooblahSpec.getSetterParameter());
 
         // property - bletch
-        PropertyDeclaration bletchSpec = props.get("bletch");
+        PropertyDeclaration bletchSpec = props.remove("bletch");
         Assert.assertNotNull(bletchSpec);
         Assert.assertTrue(bletchSpec.isShared());
+        Assert.assertFalse(bletchSpec.isPropertyGeneric());
         CustomProperty bletchProp = (CustomProperty) bletchSpec.getPropertyFactory().create();
         ((CustomProperty.CustomFactoryWithAttributes) bletchSpec.getPropertyFactory())
                 .setDefaultValue(bletchProp, 0);
         Assert.assertEquals("hasBletch", bletchSpec.getGetterMethod());
         Assert.assertEquals("setBletch", bletchSpec.getSetterMethod());
         Assert.assertEquals(0, bletchSpec.getSetterParameter());
+
+        // property - superValue
+        PropertyDeclaration superSpec = props.remove("superValue");
+        Assert.assertNotNull(superSpec);
+        Assert.assertFalse(superSpec.isShared());
+        Assert.assertFalse(superSpec.isPropertyGeneric());
+        IntProperty superProp = (IntProperty) superSpec.getPropertyFactory().create();
+        ((IntProperty.Factory) superSpec.getPropertyFactory()).setDefaultValue(superProp, 0);
+        Assert.assertEquals(0, superProp.get(0));
+        Assert.assertEquals("getSuperValue", superSpec.getGetterMethod());
+        Assert.assertEquals("setSuperValue", superSpec.getSetterMethod());
+        Assert.assertEquals(0, superSpec.getSetterParameter());
+
+        // property - enum
+        PropertyDeclaration enumSpec = props.remove("enum");
+        Assert.assertNotNull(enumSpec);
+        Assert.assertFalse(enumSpec.isShared());
+        Assert.assertTrue(enumSpec.isPropertyGeneric());
+        EnumProperty enumProp = (EnumProperty) enumSpec.getPropertyFactory().create();
+        ((EnumProperty.Factory) enumSpec.getPropertyFactory()).setDefaultValue(enumProp, 0);
+        Assert.assertEquals(ComplexComponent.TestEnum.V1, enumProp.get(0));
+        Assert.assertEquals("getEnum", enumSpec.getGetterMethod());
+        Assert.assertEquals("setEnum", enumSpec.getSetterMethod());
+        Assert.assertEquals(0, enumSpec.getSetterParameter());
+
+        // no other properties
+        Assert.assertTrue(props.isEmpty());
     }
 }