Commits

Michael Ludwig committed 348eb08

Add @Clone attribute for property declarations

Comments (0)

Files changed (3)

     <version>1.5.3-SNAPSHOT</version>
 
     <name>Entreri Entity-Component Framework</name>
-    <description>
-    Entreri is an entity-component framework for Java that helps manage or remove complex OO hierarchies that often form when developing games. For a useful description of an entity-component framework, see http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/
-    </description>
+    <description>Entreri is an entity-component framework for Java that helps manage or remove complex OO hierarchies that often form when developing games. For a useful description of an entity-component framework, see http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/</description>
     <url>http://entreri.lhkbob.com</url>
 
     <parent>

src/main/java/com/lhkbob/entreri/property/AbstractPropertyFactory.java

  */
 public abstract class AbstractPropertyFactory<P extends Property> implements PropertyFactory<P> {
     protected final Attributes attributes;
+    protected final Clone.Policy clonePolicy;
 
     public AbstractPropertyFactory(Attributes attrs) {
         attributes = attrs;
+
+        if (attrs != null && attrs.hasAttribute(Clone.class)) {
+            clonePolicy = attrs.getAttribute(Clone.class).value();
+        } else {
+            clonePolicy = Clone.Policy.JAVA_DEFAULT;
+        }
     }
 
     @Override
     public void clone(P src, int srcIndex, P dst, int dstIndex) {
-        src.getDataStore().copy(srcIndex, 1, dst.getDataStore(), dstIndex);
+        switch (clonePolicy) {
+        case DISABLE:
+            // assign default value
+            setDefaultValue(dst, dstIndex);
+            break;
+        case INVOKE_CLONE:
+            // fall through, since default implementation of INVOKE_CLONE is to
+            // just function like JAVA_DEFAULT
+        case JAVA_DEFAULT:
+            src.getDataStore().copy(srcIndex, 1, dst.getDataStore(), dstIndex);
+            break;
+        default:
+            throw new UnsupportedOperationException("Enum value not supported: " + clonePolicy);
+        }
     }
 }

src/main/java/com/lhkbob/entreri/property/ObjectProperty.java

  */
 package com.lhkbob.entreri.property;
 
+import java.lang.reflect.Method;
+
 import com.lhkbob.entreri.Attributes;
 import com.lhkbob.entreri.Factory;
 import com.lhkbob.entreri.IndexedDataStore;
      * 
      * @author Michael Ludwig
      */
-    @SuppressWarnings("rawtypes")
+    @SuppressWarnings({"rawtypes", "unchecked"})
     public static class Factory extends AbstractPropertyFactory<ObjectProperty> {
         private final Object defaultValue;
 
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public void setDefaultValue(ObjectProperty property, int index) {
             property.set(defaultValue, index);
         }
+
+        @Override
+        public void clone(ObjectProperty src, int srcIndex, ObjectProperty dst,
+                          int dstIndex) {
+            Object orig = src.get(srcIndex);
+
+            if (clonePolicy == Clone.Policy.INVOKE_CLONE && orig instanceof Cloneable) {
+                try {
+                    // if they implemented Cloneable properly, clone() should
+                    // be public and take no arguments
+                    Method cloneMethod = orig.getClass().getMethod("clone");
+                    Object cloned = cloneMethod.invoke(orig);
+                    dst.set(cloned, dstIndex);
+                } catch (Exception e) {
+                    // if they implement Cloneable, this shouldn't fail
+                    // and if it does it's not really our fault
+                    throw new RuntimeException(e);
+                }
+            } else {
+                super.clone(src, srcIndex, dst, dstIndex);
+            }
+        }
     }
 }