Commits

Michael Ludwig committed 06687bc

Implement setFactory() logic and tests.

  • Participants
  • Parent commits a295fd1

Comments (0)

Files changed (5)

src/main/java/com/googlecode/entreri/EntitySystem.java

         entityInsert = 1;
     }
     
+    @SuppressWarnings("unchecked")
     public <T extends ComponentData<T>> void setFactory(TypeId<T> id, ComponentDataFactory<T> factory) {
-        // FIXME: setting a factory will create the ComponentRepository, it cannot assign
-        // the factory if the index already exists
-        // any other action that requires an index for a type will create the index
-        // with the reflection default
+        int index = id.getId();
+        if (index >= componentIndices.length) {
+            // make sure it's the correct size
+            componentIndices = Arrays.copyOf(componentIndices, index + 1);
+        }
+        
+        ComponentRepository<T> i = (ComponentRepository<T>) componentIndices[index];
+        if (i != null) {
+            // a factory is already defined
+            throw new IllegalStateException("A ComponentDataFactory is already assigned to the type: " + id);
+        }
+        
+        // verify that the factory creates the proper instances
+        T data = factory.createInstance();
+        if (!id.getType().isInstance(data)) {
+            throw new IllegalArgumentException("ComponentDataFactory does not create instances of type: " + id);
+        }
+        
+        i = new ComponentRepository<T>(this, id, factory);
+        i.expandEntityIndex(entities.length);
+        componentIndices[index] = i;
     }
     
     public <T extends ComponentData<T>> T createDataInstance(TypeId<T> id) {

src/test/java/com/googlecode/entreri/SystemTest.java

 import org.junit.Assert;
 import org.junit.Test;
 
+import com.googlecode.entreri.component.CustomFactoryComponent;
+import com.googlecode.entreri.component.CustomFactoryComponent.CustomFactory;
+import com.googlecode.entreri.component.DefaultFactoryComponent;
 import com.googlecode.entreri.component.FloatComponent;
 import com.googlecode.entreri.component.IntComponent;
 import com.googlecode.entreri.component.MultiPropertyComponent;
 
 public class SystemTest {
     @Test
+    public void testCustomFactory() {
+        EntitySystem system = new EntitySystem();
+        system.setFactory(TypeId.get(CustomFactoryComponent.class), new CustomFactory());
+        
+        // the default reflection factory will fail to create an instance
+        // because the property is public. If it is created, and it's not null
+        // we know the custom factory worked
+        CustomFactoryComponent cd = system.createDataInstance(TypeId.get(CustomFactoryComponent.class));
+        Assert.assertNotNull(cd.prop);
+    }
+    
+    @Test
+    public void testDefaultFactoryOverride() {
+        EntitySystem system = new EntitySystem();
+        
+        // the default reflection factory will fail to create an instance
+        // because the property is public. If it is created, and it's not null
+        // we know the custom factory worked
+        DefaultFactoryComponent cd = system.createDataInstance(TypeId.get(DefaultFactoryComponent.class));
+        Assert.assertNotNull(cd.prop);
+    }
+    
+    @Test
     public void testAddEntity() {
         // There really isn't much to test with this one, everything else
         // is validated by other tests in this package

src/test/java/com/googlecode/entreri/component/CustomFactoryComponent.java

+package com.googlecode.entreri.component;
+
+import java.util.Collections;
+import java.util.Map;
+
+import com.googlecode.entreri.ComponentData;
+import com.googlecode.entreri.ComponentDataFactory;
+import com.googlecode.entreri.property.IntProperty;
+import com.googlecode.entreri.property.Property;
+import com.googlecode.entreri.property.PropertyFactory;
+
+public class CustomFactoryComponent extends ComponentData<CustomFactoryComponent> {
+    public IntProperty prop;
+    
+    public static class CustomFactory implements ComponentDataFactory<CustomFactoryComponent> {
+        @Override
+        public Map<String, PropertyFactory<?>> getPropertyFactories() {
+            return Collections.<String, PropertyFactory<?>>singletonMap("prop", IntProperty.factory(1));
+        }
+
+        @Override
+        public CustomFactoryComponent createInstance() {
+            return new CustomFactoryComponent();
+        }
+
+        @Override
+        public void setProperty(CustomFactoryComponent instance, String key, Property property) {
+            if (key.equals("prop")) {
+                instance.prop = (IntProperty) property;
+            } else {
+                throw new RuntimeException();
+            }
+        }
+    }
+}

src/test/java/com/googlecode/entreri/component/DefaultComponentDataFactory.java

+package com.googlecode.entreri.component;
+
+import java.util.Collections;
+import java.util.Map;
+
+import com.googlecode.entreri.ComponentDataFactory;
+import com.googlecode.entreri.property.IntProperty;
+import com.googlecode.entreri.property.Property;
+import com.googlecode.entreri.property.PropertyFactory;
+
+public class DefaultComponentDataFactory implements ComponentDataFactory<DefaultFactoryComponent> {
+    @Override
+    public Map<String, PropertyFactory<?>> getPropertyFactories() {
+        return Collections.<String, PropertyFactory<?>>singletonMap("prop", IntProperty.factory(1));
+    }
+
+    @Override
+    public DefaultFactoryComponent createInstance() {
+        return new DefaultFactoryComponent();
+    }
+
+    @Override
+    public void setProperty(DefaultFactoryComponent instance, String key, Property property) {
+        if (key.equals("prop")) {
+            instance.prop = (IntProperty) property;
+        } else {
+            throw new RuntimeException();
+        }
+    }
+}

src/test/java/com/googlecode/entreri/component/DefaultFactoryComponent.java

+package com.googlecode.entreri.component;
+
+import com.googlecode.entreri.ComponentData;
+import com.googlecode.entreri.annot.DefaultFactory;
+import com.googlecode.entreri.property.IntProperty;
+
+@DefaultFactory(DefaultComponentDataFactory.class)
+public class DefaultFactoryComponent extends ComponentData<DefaultFactoryComponent> {
+    public IntProperty prop;
+}