Commits

Michael Ludwig committed ecb4acf

Documentation improvements

  • Participants
  • Parent commits c8af7be

Comments (0)

Files changed (4)

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

  * property. The property type is inspected from the return type of the method. The
  * property name is the method name minus the 'get'/'is'/'has' prefix with its first
  * letter made lower-case. The {@link Named} annotation can be used to override the
- * name.</li> <li>Void, single-argument methods starting with 'set' are assumed to be a
- * setter corresponding to a property. The single parameter's type must equal the type the
+ * name.</li> <li>Single-argument methods starting with 'set' are assumed to be a setter
+ * corresponding to a property. The single parameter's type must equal the type the
  * getter. The {@link Named} annotation can be applied to either the setter or the
- * parameter to specify the property name.</li> <li>Void, multi-argument methods starting
- * with 'set' are assumed to be a setter that assigns values to multiple property, one for
- * each argument. Each argument must be annotated with {@link Named} to specify the
- * property, and the argument type must equal the type of the matching property.</li>
- * <li>Getters with void return types or arguments, setters without a return type or no
- * arguments, and any other method not matching the conventions above will cause the
- * system to throw an {@link IllegalComponentDefinitionException}.</li> </ol>
+ * parameter to specify the property name.</li> <li>Multi-argument methods starting with
+ * 'set' are assumed to be a setter that assigns values to multiple property, one for each
+ * argument. Each argument must be annotated with {@link Named} to specify the property,
+ * and the argument type must equal the type of the matching property.</li> <li>Setter
+ * methods must return void or return the components type, in which case the proxy will
+ * return itself to allow for method chaining.</li> <li>Getters with void return types or
+ * more than 0 arguments, setters with an invalid return type or no arguments, and any
+ * other method not matching the conventions above will cause the system to throw an
+ * {@link IllegalComponentDefinitionException}.</li> </ol>
  * <p/>
  * Internally, the entity system will generate proxy implementations of the component
  * interfaces that implement the property getters and setters but store all of the values

File src/main/java/com/lhkbob/entreri/ComponentFactoryProvider.java

 
     public static String generateJavaCode(Class<? extends Component> type,
                                           List<PropertySpecification> spec) {
-        return null;
+        String implName = type.getSimpleName() + "Impl";
+
+        // FIXME what package do we put the generated classes in?
+        // FIXME if AbstractComponent remains package-private then we can't put them
+        // FIXME in the package of the incoming type
+        StringBuilder sb = new StringBuilder();
+        sb.append("package ").append(type.getPackage().getName()).append(";\n")
+          .append("public class ").append(implName)
+          .append(" extends com.lhkbob.entreri.AbstractComponent implements ")
+          .append(type.getName()).append("{\n");
+        // FIXME can't just use class.getName(), have to replace the $ with a .
+
+        // FIXME handle shared instances needing members, and multi-param setters
+        int i = 0;
+        for (PropertySpecification s : spec) {
+            // FIXME nicer access to this
+            Class<?> pt = s.getGetterMethod().getReturnType();
+            // FIXME handle return this component setters as well
+            sb.append("\tpublic void ").append(s.getSetterMethod().getName()).append('(')
+              .append(pt.getName()).append(' ').append(s.getName()).append(") {\n")
+              .append("\t\towner.getProperty(").append(i).append(").set(")
+              .append(s.getName()).append(", getIndex());\n\t}\n\n");
+            sb.append("\tpublic ").append(pt.getName()).append(' ')
+              .append(s.getGetterMethod().getName()).append("() {\n")
+              .append("\t\treturn owner.getProperty(").append(i)
+              .append(").get(getIndex());\n\t}\n\n");
+            i++;
+        }
+        sb.append("}\n");
+        return sb.toString();
     }
 }

File src/main/java/com/lhkbob/entreri/PropertySpecification.java

     private final Method getter;
     private final boolean isSharedInstance;
 
-    private PropertySpecification(String name, PropertyFactory<?> factory, Method getter,
-                                  Method setter, int setterParameter) {
+    PropertySpecification(String name, PropertyFactory<?> factory, Method getter,
+                          Method setter, int setterParameter) {
         this.name = name;
         this.factory = factory;
         this.getter = getter;
 
     public static List<PropertySpecification> getSpecification(
             Class<? extends Component> componentDefinition) {
-        if (Component.class.isAssignableFrom(componentDefinition)) {
+        if (!Component.class.isAssignableFrom(componentDefinition)) {
             throw new IllegalArgumentException("Class must extend Component");
         }
         if (!componentDefinition.isInterface()) {
         Map<String, Integer> setterParameters = new HashMap<String, Integer>();
 
         for (int i = 0; i < methods.length; i++) {
-            // exclude methods defined in Component
-            if (methods[i].getDeclaringClass().equals(Component.class)) {
+            // exclude methods defined in Component, Owner, and Ownable
+            Class<?> md = methods[i].getDeclaringClass();
+            if (md.equals(Component.class) || md.equals(Owner.class) ||
+                md.equals(Ownable.class)) {
                 continue;
             }
 
             if (!Component.class.isAssignableFrom(methods[i].getDeclaringClass())) {
                 throw new IllegalComponentDefinitionException(componentDefinition,
                                                               "Method is defined in non-Component interface: " +
-                                                              methods[i]
-                                                                      .getDeclaringClass());
+                                                              md);
             }
 
             if (methods[i].getName().startsWith("is")) {
                 processSetter(methods[i], setters, setterParameters);
             } else {
                 throw new IllegalComponentDefinitionException(
-                        (Class<? extends Component>) methods[i].getDeclaringClass(),
+                        (Class<? extends Component>) md,
                         "Illegal property method: " + methods[i]);
             }
         }
                                            " does not implement required get() method for type " +
                                            baseType);
             }
-            Method s = propertyType.getMethod("set", int.class, baseType);
+            // FIXME switch back to int, type method but then we have to update all the property defs
+            Method s = propertyType.getMethod("set", baseType, int.class);
             if (!s.getReturnType().equals(void.class)) {
                 throw new RuntimeException(propertyType +
                                            " does not implement required set() method for type " +

File src/main/java/com/lhkbob/entreri/property/Factory.java

 package com.lhkbob.entreri.property;
 
 import com.lhkbob.entreri.property.IntProperty.DefaultInt;
-import com.lhkbob.entreri.property.PropertyFactory;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
  * <p/>
  * Factory can also be placed at the type level on a Property implementation to declare
  * the default PropertyFactory to use. When using the {@link ReflectionComponentDataFactory},
- * it checks for a constructor taking a single {@link com.lhkbob.entreri.property.Attributes} object, or the default
- * constructor.
+ * it checks for a constructor taking a single {@link com.lhkbob.entreri.property.Attributes}
+ * object, or the default constructor.
  *
  * @author Michael Ludwig
  * @see ReflectionComponentDataFactory
  */
 @Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.FIELD, ElementType.TYPE })
+@Target({ ElementType.METHOD, ElementType.TYPE })
 public @interface Factory {
     /**
      * @return Class of the PropertyFactory to instantiate, must have an accessible