Changeset 87 for java


Ignore:
Timestamp:
06/28/13 11:56:03 (12 years ago)
Author:
psniegowski
Message:

HIGHLIGHTS:

  • FramsClass? and contained Param are now immutable classes (like String),

which allows to refer to them concurrently without synchronization
(which for example in turn simplifies GUI management)

  • also make Path immutable (which was earlier only assumed)
  • add global cache for FramsClasses? created solely and automatically

on base of Java classes.

representations basing on given FramsClass?

  • above changes greatly improved GUI responsivness during browsing
  • furtherly improve Param class hierarchy
  • allow to inject actions on state changes into MultiParamLoader?
  • add more tests

CHANGELOG:

Add StatusListener? to MultiParamLoader?.

Minor refactorization in MultiParamLoader?.

First step with auto append.

Add SchemaTest?.

Improve Registry.

Clean up in Registry.

Work out Registry.

Use annotations for Param.

Fix ListChange?.

Improve fluent interface of the FramsClassBuilder?.

Done caching of ReflectionAccess?.Backend

Fix hashCode of Pair.

A step on a way to cache ReflectionAccess?.Backend

Make SimpleAbstractAccess?.framsClass a final field.

Add static cache for FramsClasses? based on java.

Only classes created strictly and automatically
based on java classes are using this cache.

Make all Params immutable.

Many improvement to make Param immutable.

Make PrimitiveParam? generic type.

Several changes to make Param immutable.

Make FramsClass? immutable.

Another improvement to Path immutability.

Several improvements to Path.

Improve PathTest?.

Configurarable MutabilityDetector?.

Location:
java/main
Files:
10 added
61 edited

Legend:

Unmodified
Added
Removed
  • java/main/pom.xml

    r86 r87  
    1818                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    1919        </properties>
     20
     21        <dependencyManagement>
     22                <dependencies>
     23                        <dependency>
     24                                <groupId>com.ibm.icu</groupId>
     25                                <artifactId>icu4j</artifactId>
     26                                <version>3.4.4</version>
     27                        </dependency>
     28                </dependencies>
     29        </dependencyManagement>
    2030        <dependencies>
    21                 <dependency>
    22                         <groupId>org.javatuples</groupId>
    23                         <artifactId>javatuples</artifactId>
    24                         <version>1.2</version>
    25                         <scope>compile</scope>
    26                 </dependency>
    2731                <dependency>
    2832                        <groupId>com.google.code.findbugs</groupId>
     
    8084                </dependency>
    8185
     86                <!-- the logic of @Immutable checking built in FindBugs is not very comprehensive -->
     87                <dependency>
     88                        <groupId>org.mutabilitydetector</groupId>
     89                        <artifactId>MutabilityDetector4FindBugs</artifactId>
     90                        <version>0.2.3</version>
     91                        <scope>test</scope>
     92                </dependency>
     93
     94                <dependency>
     95                        <groupId>org.mutabilitydetector</groupId>
     96                        <artifactId>MutabilityDetector</artifactId>
     97                        <version>0.9</version>
     98                        <scope>test</scope>
     99                </dependency>
    82100                <!-- <dependency> -->
    83101                <!--    <groupId>junit</groupId> -->
  • java/main/src/main/java/com/framsticks/core/Instance.java

    r86 r87  
    3333        protected void run() {
    3434                super.run();
    35                 root = new Node((CompositeParam) Param.build().name("Instance").id(name).type("o").finish(), null);
     35                root = new Node(Param.build().name("Instance").id(name).type("o"), null);
    3636                com.framsticks.model.Package.register(registry);
    3737        }
     
    267267                if ("/".equals(file.getPath())) {
    268268                        if (root.getParam().getContainedTypeName() == null) {
    269                                 root = new Node((CompositeParam)Param.build().name("Instance").id(name).type("o " + framsClass.getId()).finish(), root.getObject());
     269                                root = new Node(Param.build().name("Instance").id(name).type("o " + framsClass.getId()), root.getObject());
    270270                        }
    271271                }
     
    306306
    307307                                        String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
     308                                        //TODO listAccessParam
    308309                                        Param param = Param.build().type("o " + accessInterface.getId()).id(id).finish();
    309310                                        Object child = accessInterface.getSelected();
     
    339340
    340341        public Path getPath(String textual) {
    341                 return new Path(this, textual);
     342                return Path.build().resolve(this, textual).finish();
    342343        }
    343344
  • java/main/src/main/java/com/framsticks/core/ListChange.java

    r85 r87  
    11package com.framsticks.core;
    22
    3 import com.framsticks.params.FramsClass;
    4 import com.framsticks.params.Param;
    5 import com.framsticks.params.types.DecimalParam;
    6 import com.framsticks.params.types.EnumParam;
    7 import com.framsticks.params.types.StringParam;
     3import com.framsticks.params.annotations.FramsClassAnnotation;
     4import com.framsticks.params.annotations.ParamAnnotation;
    85import com.framsticks.util.lang.Strings;
    9 
    10 import java.util.Arrays;
    116
    127/**
    138 * @author Piotr Sniegowski
    149 */
     10@FramsClassAnnotation
    1511public class ListChange {
    1612
     
    3127                Remove,
    3228                Modify
     29                // Add(0),
     30                // Remove(1),
     31                // Modify(2);
     32
     33                // public final int value;
     34
     35                // /**
     36                //  * @param value
     37                //  */
     38                // Action(int value) {
     39                //      this.value = value;
     40                // }
     41
    3342        }
    3443
    35         private Action action;
    36         private Integer position;
    37         private String identifier;
     44        public Action action = Action.Add;
     45        @ParamAnnotation(id = "pos")
     46        public Integer position;
     47        @ParamAnnotation(id = "id")
     48        public String identifier;
    3849
     50        @ParamAnnotation
    3951        public Integer getType() { return action.ordinal(); }
     52        @ParamAnnotation
    4053        public void setType(Integer type) { action = Action.values()[type]; }
    41 
    42         public Integer getPos() { return position; }
    43         public void setPos(Integer pos) { position = pos; }
    44 
    45         public String getId() { return identifier; }
    46         public void setId(String id) { identifier = id; }
    4754
    4855        public String getBestIdentifier() {
     
    5360        }
    5461
    55         public static FramsClass getFramsClass() {
    56                 return new FramsClass("ListChange", "ListChange", null)
    57                                 .append(Param.build().id("type").name("type").type(new EnumParam(Arrays.asList("Add", "Remove", "Modify"))))
    58                                 .append(Param.build().id("id").name("identifier").type(StringParam.class))
    59                                 .append(Param.build().id("pos").name("position").type(DecimalParam.class));
    60         }
    61 
    6262        @Override
    6363        public String toString() {
  • java/main/src/main/java/com/framsticks/core/Node.java

    r84 r87  
    11package com.framsticks.core;
    22
     3import javax.annotation.Nonnull;
     4import javax.annotation.concurrent.Immutable;
     5
    36import com.framsticks.params.CompositeParam;
     7import com.framsticks.params.ParamBuilder;
    48
    59/**
    610 * @author Piotr Sniegowski
    711 */
     12@Immutable
    813public class Node {
    914
    10     protected final CompositeParam param;
    11     protected final Object object;
    12     //protected final Map<String, Node> children = new HashMap<String, Node>();
     15        protected final CompositeParam param;
     16        protected final Object object;
     17        //protected final Map<String, Node> children = new HashMap<String, Node>();
    1318
    14     public Node() {
    15         param = null;
    16         object = null;
    17     }
     19        public Node() {
     20                param = null;
     21                object = null;
     22        }
    1823
    19     public Node(CompositeParam param, Object object) {
    20         assert param != null;
    21         this.param = param;
    22         this.object = object;
    23     }
     24        public Node(@Nonnull CompositeParam param, Object object) {
     25                assert param != null;
     26                this.param = param;
     27                this.object = object;
     28        }
    2429
    25     public final CompositeParam getParam() {
    26         return param;
    27     }
     30        public Node(@Nonnull ParamBuilder builder, Object object) {
     31                this((CompositeParam) builder.finish(), object);
     32        }
    2833
    29     public final Object getObject() {
    30         return object;
    31     }
     34        public final CompositeParam getParam() {
     35                return param;
     36        }
     37
     38        public final Object getObject() {
     39                return object;
     40        }
    3241
    3342}
  • java/main/src/main/java/com/framsticks/core/Path.java

    r85 r87  
    1111
    1212import javax.annotation.concurrent.Immutable;
    13 import javax.annotation.Nonnull;
    1413
    1514import org.apache.commons.collections.ListUtils;
     
    1918 */
    2019@Immutable
    21 public class Path {
     20public final class Path {
    2221        // private final static Logger log = Logger.getLogger(Path.class.getName());
    2322
    24         final LinkedList<Node> nodes = new LinkedList<Node>();
    25         String textual;
    26         Instance instance;
    27 
    28         protected Object getKnownChild(AccessInterface access, CompositeParam param) {
     23        final Instance instance;
     24        final String textual;
     25        final LinkedList<Node> nodes;
     26
     27        protected static Object getKnownChild(Instance instance, AccessInterface access, CompositeParam param) {
    2928                Object child = access.get(param, Object.class);
    3029                if (child == null) {
     
    3433        }
    3534
    36         // public Path constructPath(Instance instance, String textual) {
    37         //      assert instance.isActive();
    38 
    39         // }
    40 
    41         Path(Instance instance, String textual) {
    42                 assert instance.isActive();
     35        /**
     36         * @param instance
     37         * @param textual
     38         * @param nodes
     39         */
     40        Path(Instance instance, String textual, LinkedList<Node> nodes) {
    4341                this.instance = instance;
    44 
    45                 nodes.add(instance.root);
    46                 Node current = instance.root;
    47 
    48                 StringBuilder b = new StringBuilder();
    49                 Iterator<String> i = Instance.splitPath(textual);
    50                 while (i.hasNext() && current.getObject() != null) {
    51                         AccessInterface access = instance.registry.prepareAccess(current.getParam());
    52                         if (access == null) {
    53                                 break;
    54                         }
    55                         String e = i.next();
    56                         Param p = access.getParam(e);
    57                         if (!(p instanceof CompositeParam)) {
    58                                 //entries.add(new Entry());
    59                                 break;
    60                         }
    61                         CompositeParam c = (CompositeParam)p;
    62                         b.append("/").append(e);
    63                         access.select(current.getObject());
    64                         current = new Node(c, getKnownChild(access, c));
    65                         nodes.add(current);
    66                 }
    67                 this.textual = (size() == 1) ? "/" : b.toString();
    68         }
    69 
    70         public Path(@Nonnull Instance instance, List<Node> nodes, Node node) {
    71                 this.instance = instance;
    72                 StringBuilder b = new StringBuilder();
    73                 boolean add = false;
    74                 for (Node n : nodes) {
    75                         this.nodes.add(n);
    76                         if (add) {
    77                                 b.append("/").append(n.getParam().getId());
    78                         }
    79                         add = true;
    80                         if (n == node) {
    81                                 break;
    82                         }
    83                 }
    84                 this.textual = (size() == 1) ? "/" : b.toString();
    85         }
    86 
    87         protected Path() {
    88 
     42                this.textual = textual;
     43                this.nodes = nodes;
    8944        }
    9045
    9146        public Path appendNode(Node node) {
    9247                assert isResolved();
    93                 Path result = new Path();
    94                 result.textual = textual + ((size() == 1) ? "" : "/") + node.getParam().getId();
    95                 result.instance = instance;
    96                 result.nodes.addAll(nodes);
    97                 result.nodes.add(node);
    98                 return result;
     48                return new PathBuilder().instance(instance).textual(textual + ((size() == 1) ? "" : "/") + node.getParam().getId()).add(nodes).add(node).finish();
    9949        }
    10050
     
    10454        }
    10555
     56        public static class PathBuilder {
     57
     58                Instance instance;
     59                String textual;
     60                final LinkedList<Node> nodes = new LinkedList<Node>();
     61
     62                public Path finish() {
     63                        assert instance != null;
     64                        assert textual != null;
     65                        return new Path(instance, textual, nodes);
     66                }
     67
     68                public PathBuilder()
     69                {
     70                }
     71
     72                public PathBuilder instance(Instance instance) {
     73                        this.instance = instance;
     74                        return this;
     75                }
     76
     77                public PathBuilder textual(String textual) {
     78                        this.textual = textual;
     79                        return this;
     80                }
     81
     82                public PathBuilder add(List<Node> nodes) {
     83                        this.nodes.addAll(nodes);
     84                        return this;
     85                }
     86
     87                public PathBuilder add(Node node) {
     88                        this.nodes.add(node);
     89                        return this;
     90                }
     91
     92                public PathBuilder setLast(Object object) {
     93                        Node n = nodes.pollLast();
     94                        nodes.add(new Node(n.getParam(), object));
     95                        return this;
     96                }
     97
     98                public PathBuilder buildUpTo(List<Node> nodes, Node node) {
     99                        StringBuilder b = new StringBuilder();
     100                        boolean add = false;
     101                        for (Node n : nodes) {
     102                                this.nodes.add(n);
     103                                if (add) {
     104                                        b.append("/").append(n.getParam().getId());
     105                                }
     106                                add = true;
     107                                if (n == node) {
     108                                        break;
     109                                }
     110                        }
     111                        this.textual = (nodes.size() == 1) ? "/" : b.toString();
     112                        return this;
     113                }
     114
     115                public PathBuilder resolve(Instance instance, String textual) {
     116
     117                        assert nodes.isEmpty();
     118                        assert instance.isActive();
     119                        this.instance = instance;
     120
     121                        nodes.add(instance.root);
     122                        Node current = instance.root;
     123
     124                        StringBuilder b = new StringBuilder();
     125                        Iterator<String> i = Instance.splitPath(textual);
     126                        while (i.hasNext() && current.getObject() != null) {
     127                                AccessInterface access = instance.registry.prepareAccess(current.getParam());
     128                                if (access == null) {
     129                                        break;
     130                                }
     131                                String e = i.next();
     132                                Param p = access.getParam(e);
     133                                if (!(p instanceof CompositeParam)) {
     134                                        //entries.add(new Entry());
     135                                        break;
     136                                }
     137                                CompositeParam c = (CompositeParam)p;
     138                                b.append("/").append(e);
     139                                access.select(current.getObject());
     140                                current = new Node(c, getKnownChild(instance, access, c));
     141                                nodes.add(current);
     142                        }
     143                        this.textual = (nodes.size() == 1) ? "/" : b.toString();
     144
     145                        return this;
     146                }
     147        }
     148
     149        public static PathBuilder build() {
     150                return new PathBuilder();
     151        }
     152
    106153        public Path appendResolution(Object object) {
    107154                assert !isResolved();
    108                 Path result = new Path();
    109                 result.textual = textual;
    110                 result.instance = instance;
    111                 result.nodes.addAll(nodes);
    112                 result.nodes.add(new Node(result.nodes.pollLast().getParam(), object));
     155                Path result = new PathBuilder().textual(textual).instance(instance).add(nodes).setLast(object).finish();
     156                assert size() == result.size();
    113157                return result;
    114158        }
     
    169213                assert !isResolved();
    170214                if (size() == 1) {
    171                         return new Path(instance, "/");//appendResolution(instance.root.object);
    172                 }
    173                 Object child = getKnownChild(instance.bindAccess(getUnder()), getTop().getParam());
     215                        return Path.build().resolve(instance, "/").finish();//appendResolution(instance.root.object);
     216                }
     217                Object child = getKnownChild(instance, instance.bindAccess(getUnder()), getTop().getParam());
    174218                if (child == null) {
    175219                        return this;
     
    201245        }
    202246
    203         public void setInstance(Instance instance) {
    204                 this.instance = instance;
    205         }
     247        // public void setInstance(Instance instance) {
     248        //      this.instance = instance;
     249        // }
    206250
    207251        @SuppressWarnings("unchecked")
  • java/main/src/main/java/com/framsticks/examples/GenotypeBrowser.java

    r85 r87  
    4242                Package.register(this.getRegistry());
    4343
    44                 registry.putInfoIntoCache(new FramsClass("ModelBuilderRoot", "ModelBuilderRoot", null)
    45                                 .append(Param.build().type("o Model").id("model").name("model"))
    46                                 .append(Param.build().type("s 1").id("genotype").name("genotype"))
     44                registry.putInfoIntoCache(FramsClass.build()
     45                                .idAndName("ModelBuilderRoot")
     46                                .param(Param.build().id("model").type("o Model").name("model"))
     47                                .param(Param.build().id("genotype").type("s 1").name("genotype"))
     48                                .finish()
    4749                );
    48                 root = new Node((CompositeParam)Param.build().type("o ModelBuilderRoot").id(name).name("Instance").finish(), PropertiesAccess.createPropertiesMap());
     50                root = new Node(Param.build().type("o ModelBuilderRoot").id(name).name("Instance"), PropertiesAccess.createPropertiesMap());
    4951        }
    5052
  • java/main/src/main/java/com/framsticks/gui/EndpointAtFrame.java

    r85 r87  
    121121                                        return result;
    122122                                }
    123                                 Path p = new Path(path.getInstance(), nodes, n);
     123                                Path p = Path.build().instance(path.getInstance()).buildUpTo(nodes, n).finish();
    124124
    125                                 //TODO breaks immutable
    126                                 path.setInstance(path.getInstance());
    127125
    128126                                log.debug("forced resolution: creating treenode for " + p);
  • java/main/src/main/java/com/framsticks/gui/Gui.java

    r84 r87  
    4242        }
    4343
    44         public static Control createComponentForText(PrimitiveParam valueParam) {
     44        public static Control createComponentForText(PrimitiveParam<?> valueParam) {
    4545                if (valueParam.getMin(Object.class) != null) {
    4646                        return new TextAreaControl(valueParam);
  • java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java

    r84 r87  
    1414        protected JScrollPane textScrollPane;
    1515
    16         public TextAreaControl(PrimitiveParam valueParam) {
     16        public TextAreaControl(PrimitiveParam<?> valueParam) {
    1717                super(valueParam);
    1818                textArea = new JTextArea();
  • java/main/src/main/java/com/framsticks/gui/controls/TextControl.java

    r84 r87  
    1010public abstract class TextControl extends ValueControl {
    1111
    12         public TextControl(PrimitiveParam valueParam) {
     12        public TextControl(PrimitiveParam<?> valueParam) {
    1313                super(valueParam);
    1414        }
  • java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java

    r84 r87  
    2323        }
    2424
    25         public TextFieldControl(PrimitiveParam valueParam) {
     25        public TextFieldControl(PrimitiveParam<?> valueParam) {
    2626                super(valueParam);
    2727                textField = new JTextField();
  • java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java

    r84 r87  
    2222        protected ValueControlListener listener;
    2323
    24         public ValueControl(PrimitiveParam primitiveParam) {
     24        public ValueControl(PrimitiveParam<?> primitiveParam) {
    2525                super(primitiveParam);
    2626
     
    4040
    4141        @Override
    42         public PrimitiveParam getParam() {
    43                 return (PrimitiveParam) param;
     42        public PrimitiveParam<?> getParam() {
     43                return (PrimitiveParam<?>) param;
    4444        }
    4545
  • java/main/src/main/java/com/framsticks/hosting/ServerInstance.java

    r86 r87  
    22
    33import com.framsticks.core.*;
    4 import com.framsticks.params.CompositeParam;
    54import com.framsticks.params.ConstructionException;
    65import com.framsticks.params.FramsClass;
    7 import com.framsticks.params.FramsClassBuilder;
    86import com.framsticks.params.Param;
    97import com.framsticks.core.LocalInstance;
     
    4442                hosted.setName("hosted");
    4543                hosted.configure(hostedConfig);
    46                 root = new Node((CompositeParam) Param.build().name("root").id("root").type("o" + hosted.getClass().getCanonicalName()).finish(), hosted);
     44                root = new Node(Param.build().name("root").id("root").type("o" + hosted.getClass().getCanonicalName()), hosted);
    4745        }
    4846
     
    5957                try {
    6058                        Class<?> nativeClass = Class.forName(id);
    61                         FramsClass framsClass = FramsClassBuilder.buildForClass(nativeClass);
     59                        FramsClass framsClass = FramsClass.build().forClass(nativeClass);
    6260
    6361                        if (!framsClass.getId().equals(id)) {
  • java/main/src/main/java/com/framsticks/leftovers/FavouritesXMLFactory.java

    r85 r87  
    2929
    3030public class FavouritesXMLFactory {
    31         private static final Logger log = Logger
    32                         .getLogger(FavouritesXMLFactory.class);
     31        private static final Logger log = Logger.getLogger(FavouritesXMLFactory.class);
    3332
    3433        private static final String PATH_MARK = "path";
  • java/main/src/main/java/com/framsticks/leftovers/f0/NeuroClass.java

    r85 r87  
    183183                StringBuilder sb = new StringBuilder();
    184184                sb.append("NeuroClass [getId=").append(framsClass.getId())
    185                                 .append(", getName=").append(framsClass.getName())
     185                                .append(", name=").append(framsClass.getName())
    186186                                .append(", description=").append(framsClass.getDescription())
    187187                                .append(", groups#=").append(framsClass.getGroupCount())
  • java/main/src/main/java/com/framsticks/observers/Observer.java

    r86 r87  
    77import com.framsticks.params.annotations.ParamAnnotation;
    88import com.framsticks.util.lang.Casting;
     9
    910import org.apache.commons.configuration.Configuration;
    1011import org.apache.log4j.Logger;
     
    5051        }
    5152
     53        // @XStreamImplicit(itemFieldName = "endpoint")
    5254        public Endpoint addEndpointForInstance(Instance instance) {
    5355                Endpoint endpoint = createEndpoint();
  • java/main/src/main/java/com/framsticks/params/AccessInterface.java

    r86 r87  
    7474        FramsClass getFramsClass();
    7575
     76        boolean tryAutoAppend(Object object);
     77
    7678
    7779}
  • java/main/src/main/java/com/framsticks/params/ArrayListAccess.java

    r86 r87  
    3131        @Override
    3232        public Param getParam(int i) {
     33                //TODO listAccessParam
    3334                return Param.build().id(Integer.toString(i)).name(elementAccess.getId()).type("o " + elementAccess.getId()).finish();
    3435        }
  • java/main/src/main/java/com/framsticks/params/CompositeParam.java

    r84 r87  
    11package com.framsticks.params;
    22
    3 import com.framsticks.util.lang.Strings;
     3import javax.annotation.concurrent.Immutable;
    44
    55/**
    66 * @author Piotr Sniegowski
    77 */
     8@Immutable
    89public abstract class CompositeParam extends ValueParam {
     10
    911        protected final String containedTypeName;
    1012
    11         public CompositeParam(String containedTypeName) {
    12                 this.containedTypeName = Strings.notEmpty(containedTypeName) ? containedTypeName : null;
     13        public CompositeParam(ParamBuilder builder) {
     14                super(builder);
     15                this.containedTypeName = builder.getContainedTypeName();
    1316        }
    1417
  • java/main/src/main/java/com/framsticks/params/FramsClass.java

    r86 r87  
    88
    99import javax.annotation.Nonnull;
     10import javax.annotation.concurrent.Immutable;
     11
     12import org.apache.log4j.Logger;
    1013
    1114/**
     
    2124 * @author Piotr Sniegowski
    2225 */
     26@Immutable
    2327@FramsClassAnnotation(id = "class", name = "class")
    2428public final class FramsClass {
    2529
    26         /** The offset of the parameter (applied for newly added parameter). */
    27         protected int fieldsNumber;
     30        private final static Logger log = Logger.getLogger(FramsClass.class);
    2831
    29         /** The groups. */
    30         protected List<Group> groups = new ArrayList<Group>();
     32        protected final String id;
     33
     34        protected final String name;
     35
     36        protected final String description;
     37
     38        protected final List<Group> groups;
     39
     40        /** The param list (for accessing parameters by offset in O(1) time. */
     41        protected final List<Param> paramList;
    3142
    3243        /**
     
    3647        protected Map<String, Param> paramEntryMap = new LinkedHashMap<String, Param>();
    3748
    38         /** The param list (for accessing parameters by offset in O(1) time. */
    39         protected List<Param> paramList = new ArrayList<Param>();
    40 
    41         /** The param getId map (for fast lookup of offset based on name */
    42         protected Map<String, Integer> paramIdMap = new HashMap<String, Integer>();
    43 
    44         protected String id;
    45 
    46         protected String name;
    47 
    48         protected String description;
     49        // /** The param getId map (for fast lookup of offset based on name */
     50        // protected Map<String, Integer> paramIdMap = new HashMap<String, Integer>();
    4951
    5052        public Collection<Param> getParamEntries() {
     
    5254        }
    5355
    54         public FramsClass() {
     56        public FramsClass(String id, String name, String description, List<Param> params, List<Group> groups) {
    5557
    56         }
     58                this.id = id;
     59                this.name = name;
     60                this.description = description;
     61                this.groups = groups;
     62                this.paramList = params;
    5763
    58         public FramsClass(String id, String name, String description) {
    59                 this.setId(id);
    60                 this.setName(name);
    61                 this.setDescription(description);
    62         }
     64                for (Param param : params) {
     65                        paramEntryMap.put(param.getId(), param);
     66                        try {
     67                                Group group = groups.get(param.getGroup());
     68                                if (group != null) {
     69                                        group.addProperty(param);
     70                                }
     71                        } catch (IndexOutOfBoundsException ignored) {
    6372
    64         /**
    65          * Adds new param entry.
    66          *
    67          * @param param
    68          *            the new param entry
    69          */
    70         public FramsClass append(Param param) {
    71                 // if (param.hasFlag(Flags.USERHIDDEN)) {
    72                 //      return this;
    73                 // }
    74                 paramEntryMap.put(param.getId(), param);
    75                 //paramEntryMap.put(param.getInternalId(), param);
    76                 paramList.add(param);
    77                 try {
    78                         Group group = groups.get(param.getGroup());
    79                         if (group != null) {
    80                                 group.addProperty(param);
    8173                        }
    82                 } catch (IndexOutOfBoundsException ignored) {
    83 
    8474                }
    8575
    86                 return this;
    87         }
     76                log.trace("created framsclass " + this);
    8877
    89         public FramsClass append(ParamBuilder builder) {
    90                 return append(builder.finish());
    91         }
    92 
    93         /**
    94          * Adds new group.
    95          */
    96         public FramsClass appendGroup(Group group) {
    97                 groups.add(group);
    98                 return this;
    9978        }
    10079
     
    206185        @Override
    207186        public String toString() {
    208                 return id;
     187                return id + "(" + name + ")";
    209188        }
    210189
    211         @ParamAnnotation
    212         public void setId(String id) {
    213                 this.id = id;
    214         }
    215 
    216         @ParamAnnotation
    217         public void setName(String name) {
    218                 this.name = name;
    219         }
    220 
    221         @ParamAnnotation(id = "desc")
    222         public void setDescription(String description) {
    223                 this.description = description;
     190        public static FramsClassBuilder build() {
     191                return new FramsClassBuilder();
    224192        }
    225193}
  • java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java

    r86 r87  
    77import java.lang.reflect.ParameterizedType;
    88import java.lang.reflect.Type;
     9import java.util.ArrayList;
     10import java.util.Collections;
     11import java.util.HashMap;
     12import java.util.LinkedList;
    913import java.util.List;
    1014import java.util.Map;
     
    1216import org.apache.log4j.Logger;
    1317
     18import com.framsticks.params.annotations.AutoAppendAnnotation;
    1419import com.framsticks.params.annotations.FramsClassAnnotation;
    1520import com.framsticks.params.annotations.ParamAnnotation;
     
    1823import com.framsticks.util.lang.Strings;
    1924
     25@FramsClassAnnotation(id = "class", name = "class")
    2026public class FramsClassBuilder {
    2127        private static final Logger log =
    2228                Logger.getLogger(FramsClassBuilder.class);
    23 
    2429
    2530        public static String getName(FramsClassAnnotation fca, Class<?> javaClass) {
     
    6368                }
    6469
    65                 if (type.equals(Integer.class) || type.equals(int.class)) {
    66                         return "d";
    67                 }
    68                 if (type.equals(String.class)) {
    69                         return "s";
    70                 }
    71                 if (type.equals(Double.class) || type.equals(double.class)) {
    72                         return "f";
    73                 }
    74                 if (type.equals(Boolean.class) || type.equals(boolean.class)) {
    75                         return "d 0 1";
    76                 }
    77                 if (type.equals(Object.class)) {
    78                         return "x";
    79                 }
    8070                if (type instanceof Class) {
     71
     72                        Class<?> cl = (Class<?>) type;
     73
     74                        // TODO: future support for enum
     75                        // if (cl.isEnum()) {
     76                        //      Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) cl;
     77                        //      Enum<?>[] enums = enumType.getEnumConstants();
     78                        //      StringBuilder b = new StringBuilder();
     79
     80                        //      b.append("d 0 ").append(enums.length - 1).append(" 0 ");
     81                        //      for (Enum<?> e : enums) {
     82                        //              b.append("~").append(e.name());
     83                        //      }
     84                        //      return b.toString();
     85                        // }
     86                        if (cl.equals(Integer.class) || cl.equals(int.class)) {
     87                                return "d";
     88                        }
     89                        if (cl.equals(String.class)) {
     90                                return "s";
     91                        }
     92                        if (cl.equals(Double.class) || cl.equals(double.class)) {
     93                                return "f";
     94                        }
     95                        if (cl.equals(Boolean.class) || cl.equals(boolean.class)) {
     96                                return "d 0 1";
     97                        }
     98                        if (cl.equals(Object.class)) {
     99                                return "x";
     100                        }
     101
    81102                        return "o " + ((Class<?>) type).getCanonicalName();
    82103                }
    83                 return null;
     104
     105                throw new ConstructionException().msg("failed to find framsticks for native type").arg("type", type);
    84106        }
    85107
     
    141163        }
    142164
    143         public static FramsClass buildForClass(Class<?> javaClass) throws ConstructionException {
     165        public static Map<Class<?>, FramsClass> synchronizedCacheForBasedOnForJavaClass = Collections.synchronizedMap(new HashMap<Class<?>, FramsClass>());
     166
     167        public FramsClass forClass(Class<?> javaClass) throws ConstructionException {
     168                FramsClass result = synchronizedCacheForBasedOnForJavaClass.get(javaClass);
     169                if (result != null) {
     170                        return result;
     171                }
     172
     173                log.info("building for class " + javaClass);
    144174
    145175                FramsClassAnnotation fca = javaClass.getAnnotation(FramsClassAnnotation.class);
    146176                if (fca == null) {
    147                         log.error(javaClass.getName() + " is not annotated with FramsClassAnnotation");
    148                         return null;
    149                 }
    150 
    151                 FramsClass framsClass = new FramsClass(getId(fca, javaClass), getName(fca, javaClass), "");
     177                        throw new ConstructionException().msg("java class is not annotated with FramsClassAnnotation").arg("java", javaClass);
     178                }
     179
     180                id(getId(fca, javaClass));
     181                name(getName(fca, javaClass));
    152182
    153183                Map<String, ParamCandidate> candidates = ParamCandidate.getAllCandidates(javaClass);
    154184
    155185                for (ParamCandidate pc : candidates.values()) {
    156                         framsClass.append(Param.build().id(pc.getId()).name(pc.getName()).type(getParamTypeForNativeType(pc.getType())).flags(pc.getFlags()));
    157                 }
    158 
    159                 return framsClass;
    160         }
     186                        param(Param.build().id(pc.getId()).name(pc.getName()).type(getParamTypeForNativeType(pc.getType())).flags(pc.getFlags()));
     187                }
     188
     189                result = finish();
     190
     191                synchronizedCacheForBasedOnForJavaClass.put(javaClass, result);
     192
     193                return result;
     194        }
     195
     196
     197        protected String id;
     198
     199        protected String name;
     200
     201        protected String description;
     202
     203        protected final List<Param> params = new LinkedList<>();
     204
     205        protected List<Group> groups = new ArrayList<Group>();
     206
     207        @ParamAnnotation
     208        public FramsClassBuilder id(String id) {
     209                this.id = id;
     210                return this;
     211        }
     212
     213        @ParamAnnotation
     214        public FramsClassBuilder name(String name) {
     215                this.name = name;
     216                return this;
     217        }
     218
     219        public FramsClassBuilder idAndName(String v) {
     220                this.id = v;
     221                this.name = v;
     222                return this;
     223        }
     224
     225        @ParamAnnotation(id = "desc")
     226        public FramsClassBuilder description(String description) {
     227                this.description = description;
     228                return this;
     229        }
     230
     231        public FramsClassBuilder() {
     232        }
     233
     234        public FramsClass finish() {
     235                return new FramsClass(id, name, description, params, groups);
     236        }
     237
     238        public FramsClassBuilder append(Param param) {
     239                params.add(param);
     240                return this;
     241        }
     242
     243        @AutoAppendAnnotation
     244        public FramsClassBuilder param(ParamBuilder builder) {
     245                return append(builder.finish());
     246        }
     247
     248        @AutoAppendAnnotation
     249        public FramsClassBuilder group(Group group) {
     250                groups.add(group);
     251                return this;
     252        }
     253
     254        /**
     255         * @return the id
     256         */
     257        @ParamAnnotation
     258        public String getId() {
     259                return id;
     260        }
     261
     262        /**
     263         * @return the name
     264         */
     265        @ParamAnnotation
     266        public String getName() {
     267                return name;
     268        }
     269
     270        /**
     271         * @return the description
     272         */
     273        @ParamAnnotation(id = "desc")
     274        public String getDescription() {
     275                return description;
     276        }
     277
     278        public FramsClassBuilder group(String group) {
     279                return group(new Group(group));
     280        }
     281
     282        public ParamBuilder param(String id) {
     283                return new ParamBuilder(this).id(id);
     284        }
     285
    161286}
  • java/main/src/main/java/com/framsticks/params/Group.java

    r77 r87  
    44import java.util.List;
    55
     6import com.framsticks.params.annotations.FramsClassAnnotation;
     7import com.framsticks.params.annotations.ParamAnnotation;
     8
    69/**
    710 * @author Piotr Sniegowski
    811 */
     12@FramsClassAnnotation
    913public class Group {
    10         String name;
     14
     15        @ParamAnnotation
     16        protected String name;
    1117
    1218        /**
     
    4046        }
    4147
    42         /*
    43                          * (non-Javadoc)
    44                          *
    45                          * @see java.lang.Object#toString()
    46                          */
    4748        @Override
    4849        public String toString() {
     
    5051        }
    5152
     53        /**
     54         * @return the name
     55         */
     56        @ParamAnnotation
     57        public String getName() {
     58                return name;
     59        }
     60
    5261}
  • java/main/src/main/java/com/framsticks/params/ListAccess.java

    r84 r87  
    7575        }
    7676
    77 }
     77        //TODO it could actually be used also
     78        @Override
     79        public boolean tryAutoAppend(Object object) {
     80                return false;
     81        }
     82
     83};
  • java/main/src/main/java/com/framsticks/params/Param.java

    r86 r87  
    22
    33
    4 import com.framsticks.params.types.DecimalParam;
    5 import com.framsticks.params.types.StringParam;
     4import javax.annotation.concurrent.Immutable;
     5
     6import com.framsticks.params.annotations.FramsClassAnnotation;
     7import com.framsticks.params.annotations.ParamAnnotation;
    68
    79/**
     
    1416 * @author Piotr Śniegowski
    1517 */
     18@Immutable
     19@FramsClassAnnotation(id = "prop", name = "prop")
    1620public abstract class Param {
    1721
    1822        /** The parameter id. */
    19         protected String id;
     23        protected final String id;
    2024
     25        //TODO
    2126        /**
    2227         * The parameter internal id. It's set by a user to use user's own getId in
    2328         * code
    2429         */
    25         protected String internalId;
     30        protected final String internalId;
    2631
    2732        /** The parameter name. */
    28         protected String name;
     33        protected final String name;
    2934
    3035        /** The help (description) concerning parameter. */
    31         protected String help;
     36        protected final String help;
    3237
    3338        /** The number of group, that parameter belongs to. */
    34         protected Integer group;
     39        protected final Integer group;
    3540
    3641        /** The getFlags stored as a bit sum. */
    37         protected Integer flags;
     42        protected final Integer flags;
    3843
     44        //TODO
    3945        /** The variable determining whether the parameter is an extra parameter. */
    40         protected Integer extra;
     46        protected final Integer extra;
    4147
    42 
    43         public Param() {
    44 
     48        public Param(ParamBuilder builder) {
     49                id = builder.getId();
     50                internalId = builder.getInternalId();
     51                name = builder.getName();
     52                help = builder.getHelp();
     53                group = builder.getGroup();
     54                flags = builder.getFlags();
     55                extra = 0;
    4556        }
    4657
     58        @ParamAnnotation
    4759        public String getId() {
    4860                return id;
     
    5365        }
    5466
     67        @ParamAnnotation
    5568        public String getName() {
    5669                return name;
    5770        }
    5871
     72        @ParamAnnotation
    5973        public String getHelp() {
    6074                return help;
    6175        }
    6276
     77        @ParamAnnotation
    6378        public Integer getGroup() {
    6479                return group;
    6580        }
    6681
     82        @ParamAnnotation
    6783        public Integer getFlags() {
    6884                return flags;
     
    7995        public Integer getExtra() {
    8096                return extra;
    81         }
    82 
    83         public void setInternalId(String internalId) {
    84                 this.internalId = internalId;
    8597        }
    8698
     
    104116        }
    105117
    106         public static FramsClass getFramsClass() {
    107                 return new FramsClass("prop", "prop", null)
    108                         .append(Param.build().id("name").name("Name").type(StringParam.class).finish())
    109                         .append(Param.build().id("id").name("Id").type(StringParam.class).finish())
    110                         .append(Param.build().id("type").name("Type").type(StringParam.class).finish())
    111                         .append(Param.build().id("help").name("Help").type(StringParam.class).finish())
    112                         .append(Param.build().id("flags").name("Flags").type(DecimalParam.class).finish());
    113         }
    114 
    115118        public static ParamBuilder build() {
    116119                return new ParamBuilder();
    117120        }
    118121
     122        public static ParamBuilder build(FramsClassBuilder builder) {
     123                return new ParamBuilder(builder);
     124        }
     125
    119126}
  • java/main/src/main/java/com/framsticks/params/ParamBuilder.java

    r86 r87  
    44import com.framsticks.params.annotations.ParamAnnotation;
    55import com.framsticks.params.types.*;
    6 import com.framsticks.util.lang.Numbers;
     6import com.framsticks.util.FramsticksException;
     7import com.framsticks.util.lang.Strings;
    78
    89import org.apache.log4j.Logger;
    910
    10 import java.util.ArrayList;
     11import java.lang.reflect.InvocationTargetException;
    1112import java.util.Arrays;
    12 
     13import java.util.List;
    1314
    1415/**
     
    5657        private Class<? extends Param> paramType;
    5758
    58         private Param param;
    59         private PrimitiveParam primitiveParam;
    60         private String typeString;
     59        private Object min;
     60
     61        private Object max;
     62
     63        private Object def;
     64
     65        String containedTypeName;
     66
     67        protected FramsClassBuilder classBuilder;
    6168
    6269        public ParamBuilder() {
     70                this(null);
     71        }
     72
     73
     74        /**
     75         * @param classBuilder
     76         */
     77        public ParamBuilder(FramsClassBuilder classBuilder) {
     78                this.classBuilder = classBuilder;
     79        }
     80
     81
     82        /**
     83         * @return the min
     84         */
     85        public Object getMin() {
     86                return min;
     87        }
     88
     89        /**
     90         * @return the max
     91         */
     92        public Object getMax() {
     93                return max;
     94        }
     95
     96        /**
     97         * @return the def
     98         */
     99        public Object getDef() {
     100                return def;
     101        }
     102
     103        public String getContainedTypeName() {
     104                return Strings.notEmpty(containedTypeName) ? containedTypeName : null;
     105        }
     106
     107        /**
     108         * @return the enumValues
     109         */
     110        public List<String> getEnumValues() {
     111                return enumValues;
     112        }
     113
     114        /**
     115         * @return the procedureSignature
     116         */
     117        public String getProcedureSignature() {
     118                return procedureSignature;
     119        }
     120
     121        /**
     122         * @return the uid
     123         */
     124        public String getUid() {
     125                return uid;
    63126        }
    64127
     
    70133         *             when Param getType is not defined
    71134         */
    72         public Param finish()  {
    73                 assert param != null;
    74                 param.id = id;
    75                 param.name = name;
    76                 param.help = help;
    77                 param.group = group;
    78                 param.flags = flags;
    79                 param.internalId = internalId;
    80                 return param;
     135        public Param finish() {
     136                try {
     137                        return paramType.getConstructor(ParamBuilder.class).newInstance(this);
     138                } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
     139                        throw new FramsticksException().msg("failed to create param").cause(e).arg("name", name);
     140                }
    81141        }
    82142
     
    87147        }
    88148
    89         protected <T extends Param> ParamBuilder internalSetType(Class<? extends Param> type, T param) {
    90                 this.paramType = type;
    91                 this.param = param;
    92                 if (param instanceof PrimitiveParam) {
    93                         primitiveParam = (PrimitiveParam) param;
    94                 }
    95                 typeString = param.getFramsTypeName();
    96                 return this;
    97         }
    98 
    99149        public <T extends Param> ParamBuilder type(Class<T> type) {
    100150                assert type != null;
    101                 try {
    102                         return internalSetType(type, type.newInstance());
    103                 } catch (InstantiationException | IllegalAccessException e) {
    104                         e.printStackTrace();
    105                 }
    106                 return this;
    107         }
    108 
    109         public <T extends Param> ParamBuilder type(T param) {
    110                 return internalSetType(param.getClass(), param);
    111         }
     151                this.paramType = type;
     152                return this;
     153        }
     154
     155        // public <T extends Param> ParamBuilder type(T param) {
     156        //      return internalSetType(param.getClass(), param);
     157        // }
    112158
    113159
     
    120166        }
    121167
     168        /**
     169         * @return the internalId
     170         */
     171        public String getInternalId() {
     172                return internalId;
     173        }
     174
    122175        public ParamBuilder setInternalId(String internalId) {
    123176                this.internalId = internalId;
     
    144197
    145198        protected <T extends Number> void parseMinMaxDefNumber(Class<T> type, String second, String third) {
    146                 if (primitiveParam == null) {
    147                         log.warn("param is not a primitive param");
    148                         return;
    149                 }
    150199                if (second != null) {
    151                         this.primitiveParam.min = Numbers.parse(second, type);
    152                         if (this.primitiveParam.min == null) {
    153                                 log.warn("value of min attribute was invalid");
    154                         }
     200                        min = second;
    155201                }
    156202                if (third != null) {
    157                         this.primitiveParam.max = Numbers.parse(third, type);
    158                         if (this.primitiveParam.max == null) {
    159                                 log.warn("value of min attribute was invalid");
    160                         }
    161                 }
    162         }
     203                        max = third;
     204                }
     205        }
     206
     207        protected List<String> enumValues;
     208
     209        public ParamBuilder enums(List<String> values) {
     210                enumValues = values;
     211                return type(EnumParam.class);
     212        }
     213
     214        protected String procedureSignature;
     215
     216        protected String uid;
    163217
    164218        @ParamAnnotation
    165219        public ParamBuilder type(String type) {
    166                 typeString = type;
     220                // typeString = type;
    167221
    168222                log.trace("parsing type: " + type);
     
    175229                switch (first.charAt(0)) {
    176230                        case 'o': {
    177                                 type(new ObjectParam(second != null ? second : first.substring(1)));
     231                                containedTypeName = second != null ? second : first.substring(1);
     232                                type(ObjectParam.class);
    178233                                break;
    179234                        }
    180235                        case 'p': {
    181                                 ProcedureParam procedureParam = new ProcedureParam();
    182                                 String signature = type.substring(1);
    183                                 try {
    184                                         procedureParam.parseSignature(signature);
    185                                 } catch (Exception e) {
    186                                         log.error("invalid procedure signature '" + signature + "': " + e);
    187                                 }
    188                                 type(procedureParam);
     236                                procedureSignature = type.substring(1);
     237                                type(ProcedureParam.class);
    189238                                break;
    190239                        }
     
    193242                                int tildeIndex = type.indexOf("~");
    194243                                if (tildeIndex != -1) {
    195                                         type(new EnumParam(new ArrayList<String>(Arrays.asList(type.substring(tildeIndex + 1).split("~")))));
     244                                        enums(Arrays.asList(type.substring(tildeIndex + 1).split("~")));
    196245                                } else {
    197246                                        if (first.length() >= 2) {
     
    214263                                                type(BooleanParam.class);
    215264                                        }
    216                                         if (param == null) {
     265                                        if (paramType == null) {
    217266                                                type(DecimalParam.class);
    218267                                        }
    219268                                }
    220                                 if (this.param instanceof DecimalParam) {
     269                                if (DecimalParam.class.isAssignableFrom(this.paramType)) {
    221270                                        parseMinMaxDefNumber(Integer.class, second, third);
    222271                                }
     
    243292                        }
    244293                        case 'l': {
    245                                 type(third != null ? new UniqueListParam(second, third) : new ArrayListParam(second));
     294                                containedTypeName = second;
     295                                if (third != null) {
     296                                        type(UniqueListParam.class);
     297                                        uid = third;
     298                                } else {
     299                                        type(ArrayListParam.class);
     300                                }
    246301                                break;
    247302                        }
     
    294349        @ParamAnnotation
    295350        public String getType() {
    296                 return typeString;
     351                return "?";
    297352        }
    298353
     
    304359        }
    305360
    306         public <T> ParamBuilder min(T min) {
    307                 if (primitiveParam != null) {
    308                         this.primitiveParam.min = min;
    309                 }
    310                 return this;
    311         }
    312 
    313         public <T> ParamBuilder max(T max) {
    314                 if (primitiveParam != null) {
    315                         this.primitiveParam.max = max;
    316                 }
    317                 return this;
    318         }
    319 
    320         public <T> ParamBuilder def(T def) {
    321                 if (def != null && primitiveParam != null) {
    322                         this.primitiveParam.def = def;
    323                 }
    324                 return this;
    325         }
    326 
    327         public Class<?> getStorageType() {
    328                 assert param != null;
    329                 return param.getStorageType();
    330         }
     361        public ParamBuilder min(Object min) {
     362                this.min = min;
     363                return this;
     364        }
     365
     366        public ParamBuilder max(Object max) {
     367                this.max = max;
     368                return this;
     369        }
     370
     371        public ParamBuilder def(Object def) {
     372                this.def = def;
     373                return this;
     374        }
     375
     376        // public Class<?> getStorageType() {
     377        //      assert param != null;
     378        //      return param.getStorageType();
     379        // }
    331380
    332381        public Param build(String line) throws Exception {
     
    386435        }
    387436
    388 
     437        public ParamBuilder defaultDef(Object def) {
     438                if (this.def == null) {
     439                        return def(def);
     440                }
     441                return this;
     442        }
    389443
    390444}
  • java/main/src/main/java/com/framsticks/params/PrimitiveParam.java

    r84 r87  
    11package com.framsticks.params;
    22
     3import com.framsticks.util.FramsticksException;
     4import com.framsticks.util.lang.Numbers;
     5
     6import javax.annotation.concurrent.Immutable;
    37
    48/**
    59 * @author Piotr Sniegowski
    610 */
    7 public abstract class PrimitiveParam extends ValueParam {
     11@Immutable
     12public abstract class PrimitiveParam<S> extends ValueParam {
    813
    914        /** The minimum allowed value of parameter. */
    10         protected Object min;
     15        protected final Object min;
    1116
    1217        /** The maximum allowed value of parameter. */
    13         protected Object max;
     18        protected final Object max;
    1419
    1520        /** The default value of parameter. */
    16         protected Object def;
     21        protected final Object def;
     22
     23        /**
     24         * @param builder
     25         */
     26        public PrimitiveParam(ParamBuilder builder) {
     27                super(builder);
     28                min = builder.getMin();
     29                max = builder.getMax();
     30                def = builder.getDef();
     31        }
    1732
    1833        public void save(SinkInterface sink, Object value) {
     
    2136
    2237        protected <T> T tryCastAndReturn(Object value, Class<T> type) {
    23                 if (value == null)
     38                if (value == null) {
    2439                        return null;
     40                }
    2541                try {
    26                         return type.cast(value);
     42                        if (type.equals(Object.class)) {
     43                                return type.cast(value);
     44                        }
     45                        if (value instanceof String) {
     46                                if (type.equals(String.class)) {
     47                                        return type.cast(value);
     48                                }
     49                                // if (Number.class.isAssignableFrom(type)) {
     50                                return Numbers.parse((String) value, type);
     51                                // }
     52                                // return null;
     53                        } else {
     54                                return type.cast(value);
     55                        }
    2756                } catch (ClassCastException e) {
    28                         throw new ClassCastException("property \"" + name
    29                                         + "\" type is \"" + value.getClass().getName()
    30                                         + "\", not \"" + type.getName() + "\"");
     57                        throw new FramsticksException().msg("failed to cast").cause(e).arg("param", this).arg("actual", value.getClass()).arg("requested", type);
    3158                }
    3259        }
     
    6491         * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
    6592         */
    66         public <T> T getDef(Class<T> type) throws ClassCastException {
     93        public <T> T getDef(Class<T> type) {
    6794                return tryCastAndReturn(def, type);
    6895        }
  • java/main/src/main/java/com/framsticks/params/PropertiesAccess.java

    r85 r87  
    2727
    2828        public PropertiesAccess(FramsClass framsClass) {
    29                 setFramsClass(framsClass);
     29                super(framsClass);
    3030        }
    3131
     
    8888        }
    8989
     90        @Override
     91        public boolean tryAutoAppend(Object object) {
     92                return false;
     93        }
    9094
    9195}
  • java/main/src/main/java/com/framsticks/params/ReflectionAccess.java

    r86 r87  
    44import java.lang.reflect.InvocationTargetException;
    55import java.lang.reflect.Method;
     6import java.util.Collections;
    67import java.util.HashMap;
    78import java.util.Map;
    89
     10import javax.annotation.concurrent.Immutable;
     11
    912import org.apache.log4j.Logger;
    1013
     14import com.framsticks.params.annotations.AutoAppendAnnotation;
    1115import com.framsticks.util.FramsticksException;
     16import com.framsticks.util.lang.Pair;
    1217
    1318import static com.framsticks.util.lang.Containers.*;
     
    2227 */
    2328public class ReflectionAccess extends SimpleAbstractAccess {
    24         private final static Logger log = Logger.getLogger(ReflectionAccess.class
    25                         .getName());
     29        private final static Logger log = Logger.getLogger(ReflectionAccess.class.getName());
    2630
    2731        protected final Class<?> reflectedClass;
     32        protected final Backend backend;
     33
    2834        private Object object;
    2935
    30 
    31         protected interface ReflectedSetter {
    32                 public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
    33         }
    34 
    35         protected interface ReflectedGetter {
    36                 public abstract <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
    37         }
    38 
    39         protected static class ReflectedValueParam {
    40                 public ReflectedSetter setter;
    41                 public ReflectedGetter getter;
    42         }
    43 
    44         protected final Map<ValueParam, ReflectedValueParam> reflectedValueParams = new HashMap<>();
     36        @Immutable
     37        public static class Backend {
     38
     39                protected static Map<Pair<Class<?>, FramsClass>, Backend> synchronizedCache = Collections.synchronizedMap(new HashMap<Pair<Class<?>, FramsClass>, Backend>());
     40
     41                public static class ReflectedValueParam {
     42                        public ReflectedSetter setter;
     43                        public ReflectedGetter getter;
     44                }
     45
     46                public interface ReflectedSetter {
     47                        public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
     48                }
     49
     50                public interface ReflectedGetter {
     51                        public abstract <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
     52                }
     53
     54                protected final Map<ValueParam, ReflectedValueParam> params;
     55                protected final Map<Class<?>, Method> autoAppendMethods;
     56
     57                /**
     58                 * @param params
     59                 */
     60                public Backend(Map<ValueParam, ReflectedValueParam> params, Map<Class<?>, Method> autoAppendMethods) {
     61                        // this.params = Collections.unmodifiableMap(params);
     62                        this.params = params;
     63                        this.autoAppendMethods = autoAppendMethods;
     64                }
     65
     66                public static Backend getOrCreateFor(Class<?> reflectedClass, FramsClass framsClass) {
     67
     68                        Pair<Class<?>, FramsClass> id = new Pair<Class<?>, FramsClass>(reflectedClass, framsClass);
     69                        Backend backend = synchronizedCache.get(id);
     70                        if (backend != null) {
     71                                return backend;
     72                        }
     73
     74                        log.debug("constructing backend for " + id);
     75                        final Map<ValueParam, ReflectedValueParam> params = new HashMap<>();
     76
     77                        Map<String, ParamCandidate> candidates = ParamCandidate.getAllCandidates(reflectedClass);
     78
     79                        try {
     80                                for (final ValueParam vp : filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) {
     81                                        if (!candidates.containsKey(vp.getId())) {
     82                                                throw new ConstructionException().msg("missing candidate for param").arg("param", vp);
     83                                        }
     84                                        ParamCandidate pc = candidates.get(vp.getId());
     85                                        if (pc.isReadOnly() && !vp.hasFlag(Flags.READONLY)) {
     86                                                throw new ConstructionException().msg("readonly state conflict").arg("param", vp);
     87                                        }
     88                                        if (!typeMatch(pc.getRawType(), vp.getStorageType())) {
     89                                                throw new ConstructionException().msg("types mismatch for param").arg("param", vp).arg("candidate", pc.getType()).arg("storage", vp.getStorageType());
     90                                        }
     91
     92                                        ReflectedValueParam rvp = new ReflectedValueParam();
     93                                        params.put(vp, rvp);
     94                                        final boolean primitive = pc.isPrimitive();
     95                                        if (pc.getField() != null) {
     96                                                final Field f = pc.getField();
     97                                                rvp.getter = new ReflectedGetter() {
     98                                                        @Override
     99                                                        public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException {
     100                                                                return type.cast(f.get(object));
     101                                                        }
     102                                                };
     103                                                if (!pc.isFinal()) {
     104                                                        rvp.setter = new ReflectedSetter() {
     105                                                                @Override
     106                                                                public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException {
     107                                                                        if (value == null && primitive) {
     108                                                                                throw new FramsticksException().msg("setting null to primitive value");
     109                                                                        }
     110                                                                        f.set(object, value);
     111                                                                }
     112                                                        };
     113                                                }
     114                                        } else {
     115                                                final Method g = pc.getGetter();
     116
     117                                                rvp.getter = new ReflectedGetter() {
     118                                                        @Override
     119                                                        public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
     120                                                                return type.cast(g.invoke(object));
     121                                                        }
     122                                                };
     123
     124                                                if (!pc.isFinal()) {
     125                                                        final Method s = pc.getSetter();
     126                                                        rvp.setter = new ReflectedSetter() {
     127                                                                @Override
     128                                                                public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
     129                                                                        if (value == null && primitive) {
     130                                                                                throw new FramsticksException().msg("setting null to primitive value");
     131                                                                        }
     132                                                                        s.invoke(object, value);
     133                                                                }
     134                                                        };
     135                                                }
     136                                        }
     137                                }
     138                        } catch (ConstructionException e) {
     139                                throw e.arg("java class", reflectedClass).arg("framsClass", framsClass);
     140                        }
     141
     142                        Map<Class<?>, Method> autoAppendMethods = new HashMap<>();
     143
     144                        Class<?> javaClass = reflectedClass;
     145                        while (javaClass != null) {
     146
     147                                for (Method m : javaClass.getDeclaredMethods()) {
     148                                        AutoAppendAnnotation a = m.getAnnotation(AutoAppendAnnotation.class);
     149                                        if (a == null) {
     150                                                continue;
     151                                        }
     152                                        Class<?>[] args = m.getParameterTypes();
     153                                        if (args.length != 1) {
     154                                                throw new ConstructionException().msg("invalid number of arguments in AutoAppend marked method").arg("method", m).arg("arguments", args.length);
     155                                        }
     156                                        autoAppendMethods.put(args[0], m);
     157                                }
     158
     159                                javaClass = javaClass.getSuperclass();
     160                        }
     161
     162                        backend = new Backend(params, autoAppendMethods);
     163                        synchronizedCache.put(id, backend);
     164                        return backend;
     165                }
     166
     167        }
    45168
    46169        public ReflectionAccess(Class<?> reflectedClass) throws ConstructionException {
    47                 this(reflectedClass, FramsClassBuilder.buildForClass(reflectedClass));
     170                this(reflectedClass, FramsClass.build().forClass(reflectedClass));
    48171        }
    49172
     
    68191
    69192        public ReflectionAccess(Class<?> reflectedClass, FramsClass framsClass) throws ConstructionException {
     193                super(framsClass);
    70194                this.reflectedClass = reflectedClass;
    71                 setFramsClass(framsClass);
    72 
    73                 Map<String, ParamCandidate> candidates = ParamCandidate.getAllCandidates(reflectedClass);
    74 
    75                 try {
    76                         for (final ValueParam vp : filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) {
    77                                 if (!candidates.containsKey(vp.getId())) {
    78                                         throw new ConstructionException().msg("missing candidate for param").arg("param", vp);
    79                                 }
    80                                 ParamCandidate pc = candidates.get(vp.getId());
    81                                 if (pc.isReadOnly() && !vp.hasFlag(Flags.READONLY)) {
    82                                         throw new ConstructionException().msg("readonly state conflict").arg("param", vp);
    83                                 }
    84                                 if (!typeMatch(pc.getRawType(), vp.getStorageType())) {
    85                                         throw new ConstructionException().msg("types mismatch for param").arg("param", vp).arg("candidate", pc.getType()).arg("storage", vp.getStorageType());
    86                                 }
    87 
    88                                 ReflectedValueParam rvp = new ReflectedValueParam();
    89                                 reflectedValueParams.put(vp, rvp);
    90                                 final boolean primitive = pc.isPrimitive();
    91                                 if (pc.getField() != null) {
    92                                         final Field f = pc.getField();
    93                                         rvp.getter = new ReflectedGetter() {
    94                                                 @Override
    95                                                 public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException {
    96                                                         return type.cast(f.get(object));
    97                                                 }
    98                                         };
    99                                         if (!pc.isFinal()) {
    100                                                 rvp.setter = new ReflectedSetter() {
    101                                                         @Override
    102                                                         public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException {
    103                                                                 if (value == null && primitive) {
    104                                                                         throw new FramsticksException().msg("setting null to primitive value");
    105                                                                 }
    106                                                                 f.set(object, value);
    107                                                         }
    108                                                 };
    109                                         }
    110                                 } else {
    111                                         final Method g = pc.getGetter();
    112 
    113                                         rvp.getter = new ReflectedGetter() {
    114                                                 @Override
    115                                                 public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    116                                                         return type.cast(g.invoke(object));
    117                                                 }
    118                                         };
    119 
    120                                         if (!pc.isFinal()) {
    121                                                 final Method s = pc.getSetter();
    122                                                 rvp.setter = new ReflectedSetter() {
    123                                                         @Override
    124                                                         public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    125                                                                 if (value == null && primitive) {
    126                                                                         throw new FramsticksException().msg("setting null to primitive value");
    127                                                                 }
    128                                                                 s.invoke(object, value);
    129                                                         }
    130                                                 };
    131                                         }
    132                                 }
    133                         }
    134                 } catch (ConstructionException e) {
    135                         throw e.arg("java class", reflectedClass).arg("framsClass", framsClass);
    136                 }
     195                this.backend = Backend.getOrCreateFor(reflectedClass, framsClass);
     196                // log.info("created ReflectionAccess " + this);
    137197        }
    138198
     
    149209                                }
    150210
    151                                 return reflectedValueParams.get(param).getter.get(object, type);
     211                                return backend.params.get(param).getter.get(object, type);
    152212                        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
    153213                                throw new FramsticksException().msg("failed to get").cause(e);
     
    169229                                        throw new FramsticksException().msg("no object set");
    170230                                }
    171                                 ReflectedSetter s = reflectedValueParams.get(param).setter;
     231                                Backend.ReflectedSetter s = backend.params.get(param).setter;
    172232                                if (s == null) {
    173233                                        throw new FramsticksException().msg("trying to set final");
     
    238298        }
    239299
    240 
    241300        @Override
    242301        public ReflectionAccess cloneAccess() throws ConstructionException {
     
    265324        }
    266325
     326        @Override
     327        public boolean tryAutoAppend(Object value) {
     328                assert object != null;
     329                for (Map.Entry<Class<?>, Method> a : backend.autoAppendMethods.entrySet()) {
     330                        if (a.getKey().isAssignableFrom(value.getClass())) {
     331                                try {
     332                                        a.getValue().invoke(object, value);
     333                                        return true;
     334                                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
     335                                        throw new FramsticksException().msg("failed to auto append").cause(e).arg("value", value).arg("into object", object).arg("with method", a.getValue());
     336                                }
     337                        }
     338                }
     339                return false;
     340        }
    267341}
    268342
  • java/main/src/main/java/com/framsticks/params/Registry.java

    r86 r87  
    55import com.framsticks.params.annotations.FramsClassAnnotation;
    66
     7import java.util.Collections;
    78import java.util.HashMap;
     9import java.util.HashSet;
    810import java.util.Map;
     11import java.util.Set;
    912
    1013/**
     
    1417        private static final Logger log = Logger.getLogger(Registry.class.getName());
    1518
    16         protected final Map<String, Class<?>> reflectedClasses = new HashMap<String, Class<?>>();
    17         protected final Map<String, String> invertedReflectedClasses = new HashMap<String, String>();
    18         protected final Map<String, FramsClass> infoCache = new HashMap<String, FramsClass>();
     19        public static class DoubleSet<K1, K2, V> {
     20                protected final Map<K1, V> byId = new HashMap<>();
     21                protected final Map<K2, V> byName = new HashMap<>();
     22                protected final Set<V> values = new HashSet<>();
    1923
    20         public final void registerReflectedClass(String name, String id, String className) {
    21                 try {
    22                         registerReflectedClass(name, id, Class.forName(className));
    23                 } catch (ClassNotFoundException e) {
    24                         log.fatal("class not found during registration: " + e);
     24                public int size() {
     25                        return values.size();
     26                }
     27
     28                public void put(K1 id, K2 name, V value) {
     29                        values.add(value);
     30                        if (id != null) {
     31                                byId.put(id, value);
     32                        }
     33                        if (name != null) {
     34                                byName.put(name, value);
     35                        }
     36                }
     37
     38                public boolean containsValue(V value) {
     39                        return values.contains(value);
     40
     41                }
     42
     43                public boolean containsKey(String identifier) {
     44                        return byId.containsKey(identifier) || byName.containsKey(identifier);
     45                }
     46
     47                public V get(String identifier) {
     48                        if (byId.containsKey(identifier)) {
     49                                return byId.get(identifier);
     50                        }
     51                        if (byName.containsKey(identifier)) {
     52                                return byName.get(identifier);
     53                        }
     54                        return null;
     55                }
     56
     57                public Set<V> getValues() {
     58                        return Collections.unmodifiableSet(values);
    2559                }
    2660        }
    2761
    28         public void registerReflectedClass(String name, String id,
    29                         Class<?> reflectedClass) {
    30                 if (name != null) {
    31                         reflectedClasses.put(name, reflectedClass);
    32                         invertedReflectedClasses.put(reflectedClass.getCanonicalName(), name);
    33                 }
    34                 if (id != null) {
    35                         reflectedClasses.put(id, reflectedClass);
    36                 }
     62        // protected void internalRegisterClass(FramsClass framsClass, @Nullable Class<?> javaClass) {
     63        //      assert framsClass.getName() != null;
     64        //      assert framsClass.getId() != null;
     65        //      infoCacheByName.put(framsClass.getName(), framsClass);
     66        //      infoCacheById.put(framsClass.getId(), framsClass);
     67
     68        //      if (javaClass != null) {
     69        //              reflectedClasses.put(framsClass, javaClass);
     70        //              infoCacheByJavaName.put(javaClass.getCanonicalName(), framsClass);
     71        //      }
     72        // }
     73        protected final DoubleSet<String, String, Class<?>> javaClasses = new DoubleSet<>();
     74        protected final DoubleSet<String, String, FramsClass> framsClasses = new DoubleSet<>();
     75
     76        public void registerReflectedClass(String name, String id, Class<?> reflectedClass) {
     77                javaClasses.put(id, name, reflectedClass);
    3778        }
    3879
     
    5091
    5192        public AccessInterface createAccess(String name, FramsClass framsClass) throws ConstructionException {
    52                 if (reflectedClasses.containsKey(name)) {
    53                         return new ReflectionAccess(reflectedClasses.get(name), framsClass);
     93                assert framsClasses.containsValue(framsClass);
     94                if (javaClasses.containsKey(name)) {
     95                        return new ReflectionAccess(javaClasses.get(name), framsClass);
    5496                }
    5597                return new PropertiesAccess(framsClass);
     
    5799
    58100        public void putInfoIntoCache(FramsClass framsClass) {
    59                 if (infoCache.containsKey(framsClass.getId())) {
    60                         log.info("already cached " + framsClass);
    61                         return;
    62                 }
    63101                log.debug("caching info for " + framsClass);
    64                 infoCache.put(framsClass.getId(), framsClass);
    65                 infoCache.put(framsClass.getName(), framsClass);
     102                framsClasses.put(framsClass.getId(), framsClass.getName(), framsClass);
    66103        }
    67104
    68         public FramsClass getInfoFromCache(String id) {
    69                 if (id == null) {
     105        public FramsClass getInfoFromCache(String identifier) {
     106                if (identifier == null) {
    70107                        return null;
    71108                }
    72                 if (infoCache.containsKey(id)) {
    73                         return infoCache.get(id);
    74                 }
    75                 if (invertedReflectedClasses.containsKey(id)) {
    76                         return getInfoFromCache(invertedReflectedClasses.get(id));
    77                 }
    78                 return null;
     109                return framsClasses.get(identifier);
    79110        }
    80111
     
    102133        }
    103134
     135        public Set<Class<?>> getReflectedClasses() {
     136                return javaClasses.getValues();
     137        }
     138
     139        public Set<FramsClass> getInfoCache() {
     140                return framsClasses.getValues();
     141        }
     142
    104143}
  • java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java

    r86 r87  
    2424        private final static Logger log = Logger.getLogger(SimpleAbstractAccess.class.getName());
    2525
     26        protected final FramsClass framsClass;
     27
     28        /**
     29         * @param framsClass
     30         */
     31        public SimpleAbstractAccess(FramsClass framsClass) {
     32                this.framsClass = framsClass;
     33        }
     34
    2635        @Override
    2736        public final FramsClass getFramsClass() {
     
    2938        }
    3039
    31         public void setFramsClass(FramsClass framsClass) {
    32                 this.framsClass = framsClass;
    33         }
    3440        /**
    3541         * Simple String key, value class.
     
    5157        }
    5258
    53         protected FramsClass framsClass;
    5459
    5560        @Override
     
    141146        @Override
    142147        public void setMin(int i) {
    143                 PrimitiveParam entry = framsClass.getParamEntry(i, PrimitiveParam.class);
     148                PrimitiveParam<?> entry = framsClass.getParamEntry(i, PrimitiveParam.class);
    144149                if (entry == null) {
    145150                        return;
     
    160165        @Override
    161166        public void setMax(int i) {
    162                 PrimitiveParam entry = framsClass.getParamEntry(i, PrimitiveParam.class);
     167                PrimitiveParam<?> entry = framsClass.getParamEntry(i, PrimitiveParam.class);
    163168                if (entry == null) {
    164169                        return;
     
    188193                assert framsClass != null;
    189194                sink.print(framsClass.getId()).print(":").breakLine();
    190                 for (PrimitiveParam p : filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
     195                for (PrimitiveParam<?> p : filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
    191196                        Object value = get(p, Object.class);
    192197                        if (value == null) {
  • java/main/src/main/java/com/framsticks/params/UniqueListAccess.java

    r85 r87  
    4444                        return getParam(i);
    4545                }
     46                //TODO list access here
    4647                return Param.build().id(id).name(elementAccess.getId()).type("o " + elementAccess.getId()).finish();
    4748        }
  • java/main/src/main/java/com/framsticks/params/ValueParam.java

    r84 r87  
    11package com.framsticks.params;
    22
     3
     4import javax.annotation.concurrent.Immutable;
    35
    46/**
    57 * @author Piotr Sniegowski
    68 */
     9@Immutable
    710public abstract class ValueParam extends Param {
     11
     12        /**
     13         * @param builder
     14         */
     15        public ValueParam(ParamBuilder builder) {
     16                super(builder);
     17        }
    818
    919        public ReassignResult<?> reassign(Object newValue, Object oldValue) throws CastFailure {
     
    1121        }
    1222
    13         public abstract <T> T getDef(Class<T> type) throws ClassCastException;
     23        public abstract <T> T getDef(Class<T> type);
    1424
    1525}
  • java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java

    r84 r87  
    44import com.framsticks.params.ArrayListAccess;
    55import com.framsticks.params.CastFailure;
     6import com.framsticks.params.ParamBuilder;
    67import com.framsticks.params.ReassignResult;
    78import com.framsticks.util.lang.Casting;
     
    1213import java.util.List;
    1314
     15import javax.annotation.concurrent.Immutable;
     16
    1417/**
    1518 * @author Piotr Sniegowski
    1619 */
     20@Immutable
    1721public class ArrayListParam extends ListParam {
    1822
    19         public ArrayListParam(String containedTypeName) {
    20                 super(containedTypeName);
     23        public ArrayListParam(ParamBuilder builder) {
     24                super(builder);
    2125        }
    2226
  • java/main/src/main/java/com/framsticks/params/types/BinaryParam.java

    r84 r87  
    22
    33import com.framsticks.params.CastFailure;
     4import com.framsticks.params.ParamBuilder;
    45import com.framsticks.params.PrimitiveParam;
    56import com.framsticks.params.ReassignResult;
    67import com.framsticks.util.lang.Numbers;
    78
     9import javax.annotation.concurrent.Immutable;
     10
    811/**
    912 * @author Piotr Sniegowski
    1013 */
    11 public class BinaryParam extends PrimitiveParam {
     14@Immutable
     15public class BinaryParam extends PrimitiveParam<Integer> {
     16
     17        /**
     18         * @param builder
     19         */
     20        public BinaryParam(ParamBuilder builder) {
     21                super(builder);
     22        }
    1223
    1324        @Override
  • java/main/src/main/java/com/framsticks/params/types/BooleanParam.java

    r84 r87  
    11package com.framsticks.params.types;
    22
     3import javax.annotation.concurrent.Immutable;
     4
    35import com.framsticks.params.CastFailure;
     6import com.framsticks.params.ParamBuilder;
    47import com.framsticks.params.PrimitiveParam;
    58import com.framsticks.params.ReassignResult;
     
    1013 * @author Piotr Sniegowski
    1114 */
    12 public class BooleanParam extends PrimitiveParam {
     15@Immutable
     16public class BooleanParam extends PrimitiveParam<Boolean> {
    1317
    14         public BooleanParam() {
    15                 def = false;
     18        /**
     19         * @param builder
     20         */
     21        public BooleanParam(ParamBuilder builder) {
     22                super(builder.defaultDef(false));
    1623        }
    1724
  • java/main/src/main/java/com/framsticks/params/types/ColorParam.java

    r84 r87  
    22
    33import com.framsticks.params.CastFailure;
     4import com.framsticks.params.ParamBuilder;
    45import com.framsticks.params.PrimitiveParam;
    56import com.framsticks.params.ReassignResult;
     7
     8import javax.annotation.concurrent.Immutable;
    69
    710/**
    811 * @author Piotr Sniegowski
    912 */
    10 public class ColorParam extends PrimitiveParam {
     13@Immutable
     14public class ColorParam extends PrimitiveParam<Object> {
     15
     16
     17
     18        /**
     19         * @param builder
     20         */
     21        public ColorParam(ParamBuilder builder) {
     22                super(builder);
     23        }
    1124
    1225        @Override
  • java/main/src/main/java/com/framsticks/params/types/DecimalParam.java

    r84 r87  
    22
    33import com.framsticks.params.CastFailure;
     4import com.framsticks.params.ParamBuilder;
    45import com.framsticks.params.ReassignResult;
     6
     7import javax.annotation.concurrent.Immutable;
    58
    69/**
    710 * @author Piotr Sniegowski
    811 */
     12@Immutable
    913public class DecimalParam extends NumberParam<Integer> {
    1014
    11         public DecimalParam() {
    12                 def = 0;
     15        /**
     16         * @param builder
     17         */
     18        public DecimalParam(ParamBuilder builder) {
     19                super(builder.defaultDef(0));
    1320        }
    1421
  • java/main/src/main/java/com/framsticks/params/types/EnumParam.java

    r84 r87  
    33import java.util.List;
    44
     5import com.framsticks.params.ParamBuilder;
     6
     7import javax.annotation.concurrent.Immutable;
     8
    59/**
    610 * @author Piotr Sniegowski
    711 */
     12@Immutable
    813public class EnumParam extends DecimalParam {
    914
    10         List<String> enums;
     15
     16        protected final List<String> enums;
    1117
    1218        /**
     
    1521         * @param enums
    1622         */
    17         public EnumParam(List<String> enums) {
    18                 assert(enums != null);
    19                 this.enums = enums;
     23        public EnumParam(ParamBuilder builder) {
     24                super(builder);
     25                this.enums = builder.getEnumValues();
     26                assert(this.enums != null);
    2027        }
    2128
  • java/main/src/main/java/com/framsticks/params/types/EventParam.java

    r84 r87  
    22
    33import com.framsticks.params.Param;
     4import com.framsticks.params.ParamBuilder;
     5
     6import javax.annotation.concurrent.Immutable;
    47
    58/**
    69 * @author Piotr Sniegowski
    710 */
     11@Immutable
    812public class EventParam extends Param {
     13
     14
     15
     16        /**
     17         * @param builder
     18         */
     19        public EventParam(ParamBuilder builder) {
     20                super(builder);
     21        }
    922
    1023        @Override
  • java/main/src/main/java/com/framsticks/params/types/FloatParam.java

    r84 r87  
    22
    33import com.framsticks.params.CastFailure;
     4import com.framsticks.params.ParamBuilder;
    45import com.framsticks.params.ReassignResult;
     6
     7import javax.annotation.concurrent.Immutable;
    58
    69/**
    710 * @author Piotr Sniegowski
    811 */
     12@Immutable
    913public class FloatParam extends NumberParam<Double> {
    1014
    11         public FloatParam() {
    12                 def = 0.0;
     15        /**
     16         * @param builder
     17         */
     18        public FloatParam(ParamBuilder builder) {
     19                super(builder.defaultDef(0.0));
    1320        }
    1421
  • java/main/src/main/java/com/framsticks/params/types/ListParam.java

    r84 r87  
    22
    33import com.framsticks.params.CompositeParam;
     4import com.framsticks.params.ParamBuilder;
     5
     6import javax.annotation.concurrent.Immutable;
    47
    58/**
    69 * @author Piotr Sniegowski
    710 */
     11@Immutable
    812public abstract class ListParam extends CompositeParam {
    913
    10         public ListParam(String containedTypeName) {
    11                 super(containedTypeName);
     14        public ListParam(ParamBuilder builder) {
     15                super(builder);
    1216        }
    1317
  • java/main/src/main/java/com/framsticks/params/types/NumberParam.java

    r84 r87  
    33import com.framsticks.params.CastFailure;
    44import com.framsticks.params.Flags;
     5import com.framsticks.params.ParamBuilder;
    56import com.framsticks.params.PrimitiveParam;
    67import com.framsticks.params.ReassignResult;
     
    89import com.framsticks.util.lang.Numbers;
    910
     11import javax.annotation.concurrent.Immutable;
     12
    1013/**
    1114 * @author Piotr Sniegowski
    1215 */
    13 public abstract class NumberParam<T extends Number & Comparable<T>> extends PrimitiveParam {
     16@Immutable
     17public abstract class NumberParam<T extends Number & Comparable<T>> extends PrimitiveParam<T> {
     18
     19        /**
     20         * @param builder
     21         */
     22        public NumberParam(ParamBuilder builder) {
     23                super(builder);
     24        }
    1425
    1526        @Override
     
    2132                T v = null;
    2233                if (newValue instanceof String) {
    23                         v = Numbers.parse((String)newValue, type);
     34                        v = Numbers.parse((String) newValue, type);
    2435                } else {
    2536                        v = Casting.tryCast(type, newValue);
  • java/main/src/main/java/com/framsticks/params/types/ObjectParam.java

    r84 r87  
    44import com.framsticks.params.CastFailure;
    55import com.framsticks.params.CompositeParam;
     6import com.framsticks.params.ParamBuilder;
    67import com.framsticks.params.ReassignResult;
     8
     9import javax.annotation.concurrent.Immutable;
    710
    811/**
    912 * @author Piotr Sniegowski
    1013 */
     14@Immutable
    1115public class ObjectParam extends CompositeParam {
    1216
    13         public ObjectParam(String containedTypeName) {
    14                 super(containedTypeName);
     17        public ObjectParam(ParamBuilder builder) {
     18                super(builder);
    1519        }
    1620
  • java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java

    r85 r87  
    22
    33import com.framsticks.params.Param;
     4import com.framsticks.params.ParamBuilder;
     5import com.framsticks.util.FramsticksException;
    46import com.framsticks.util.lang.Strings;
    57
     
    911import java.util.regex.Pattern;
    1012
     13import javax.annotation.concurrent.Immutable;
     14
    1115/**
    1216 * @author Piotr Sniegowski
    1317 */
     18@Immutable
    1419public class ProcedureParam extends Param {
    15         private Param resultType;
    16         private List<Param> argumentsType = new ArrayList<Param>();
     20        private final Param resultType;
     21        private final List<Param> argumentsType = new ArrayList<Param>();
    1722
    1823        private static Pattern addressPattern = Pattern.compile("^([^\\(]+)?\\(([^\\)]*)\\)$");
     24
     25        /**
     26         * @param builder
     27         */
     28        public ProcedureParam(ParamBuilder builder) {
     29                super(builder);
     30                String signature = builder.getProcedureSignature();
     31                if (Strings.notEmpty(signature)) {
     32                        Matcher matcher = addressPattern.matcher(signature);
     33                        if (!matcher.matches()) {
     34                                throw new FramsticksException().msg("invalid signature");
     35                        }
     36                        String result = Strings.collapse(matcher.group(1));
     37                        resultType = (result != null) ? parseType(result, null) : null;
     38                        String arguments = matcher.group(2);
     39                        if (!Strings.notEmpty(arguments)) {
     40                                return;
     41                        }
     42                        for (String a : arguments.split(",")) {
     43                                int space = a.indexOf(' ');
     44                                String type;
     45                                String name;
     46                                if (space == -1) {
     47                                        type = a;
     48                                        name = null;
     49                                } else {
     50                                        type = a.substring(0, space);
     51                                        name = a.substring(space + 1);
     52                                }
     53                                argumentsType.add(parseType(type, name));
     54                        }
     55                } else {
     56                        resultType = null;
     57                }
     58        }
    1959
    2060        protected static Param parseType(String type, String name) {
    2161                return Param.build().type(type).name(name).finish();
    2262        }
    23 
    24         public void parseSignature(String signature) throws Exception {
    25                 if (!Strings.notEmpty(signature)) {
    26                         return;
    27                 }
    28                 Matcher matcher = addressPattern.matcher(signature);
    29                 if (!matcher.matches()) {
    30                         throw new Exception("invalid signature");
    31                 }
    32                 String result = Strings.collapse(matcher.group(1));
    33                 if (result != null) {
    34                         resultType = parseType(result, null);
    35                 }
    36                 String arguments = matcher.group(2);
    37                 if (!Strings.notEmpty(arguments)) {
    38                         return;
    39                 }
    40                 for (String a : arguments.split(",")) {
    41                         int space = a.indexOf(' ');
    42                         String type;
    43                         String name;
    44                         if (space == -1) {
    45                                 type = a;
    46                                 name = null;
    47                         } else {
    48                                 type = a.substring(0, space);
    49                                 name = a.substring(space + 1);
    50                         }
    51                         argumentsType.add(parseType(type, name));
    52                 }
    53         }
    54 
    5563
    5664        @Override
  • java/main/src/main/java/com/framsticks/params/types/StringParam.java

    r84 r87  
    22
    33import com.framsticks.params.CastFailure;
     4import com.framsticks.params.ParamBuilder;
    45import com.framsticks.params.PrimitiveParam;
    56import com.framsticks.params.ReassignResult;
    67import com.framsticks.params.SinkInterface;
    78
     9import javax.annotation.concurrent.Immutable;
     10
    811/**
    912 * @author Piotr Sniegowski
    1013 */
    11 public class StringParam extends PrimitiveParam {
     14@Immutable
     15public class StringParam extends PrimitiveParam<String> {
     16
     17
     18
     19        /**
     20         * @param builder
     21         */
     22        public StringParam(ParamBuilder builder) {
     23                super(builder);
     24        }
     25
    1226        @Override
    1327        public Class<?> getStorageType() {
  • java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java

    r84 r87  
    33import com.framsticks.params.AccessInterface;
    44import com.framsticks.params.CastFailure;
     5import com.framsticks.params.ParamBuilder;
    56import com.framsticks.params.ReassignResult;
    67import com.framsticks.params.UniqueListAccess;
     
    1011import java.util.Map;
    1112
     13import javax.annotation.concurrent.Immutable;
     14
    1215/**
    1316 * @author Piotr Sniegowski
    1417 */
     18@Immutable
    1519public class UniqueListParam extends ListParam {
    1620
    1721        final String uidName;
    1822
    19         public UniqueListParam(String containedTypeName, String uidName) {
    20                 super(containedTypeName);
    21                 this.uidName = uidName;
     23        public UniqueListParam(ParamBuilder builder) {
     24                super(builder);
     25                this.uidName = builder.getUid();
    2226        }
    2327
  • java/main/src/main/java/com/framsticks/params/types/UniversalParam.java

    r84 r87  
    22
    33import com.framsticks.params.CastFailure;
     4import com.framsticks.params.ParamBuilder;
    45import com.framsticks.params.PrimitiveParam;
    56import com.framsticks.params.ReassignResult;
     7
     8import javax.annotation.concurrent.Immutable;
    69
    710/**
    811 * @author Piotr Sniegowski
    912 */
    10 public class UniversalParam extends PrimitiveParam {
     13@Immutable
     14public class UniversalParam extends PrimitiveParam<Object> {
     15
     16
     17        /**
     18         * @param builder
     19         */
     20        public UniversalParam(ParamBuilder builder) {
     21                super(builder);
     22        }
     23
    1124        @Override
    1225        public Class<?> getStorageType() {
  • java/main/src/main/java/com/framsticks/parsers/F0Parser.java

    r86 r87  
    176176                        return exceptions;
    177177                }
    178                 for (PrimitiveParam p : Containers.filterInstanceof(paramsC, PrimitiveParam.class)) {
     178                for (PrimitiveParam<?> p : Containers.filterInstanceof(paramsC, PrimitiveParam.class)) {
    179179                        Object def = p.getDef(Object.class);
    180180                        if (def != null) {
     
    209209                                if (currentParam != null) {
    210210                                        if (pair.value != null) {
    211                                                 PrimitiveParam vp = (PrimitiveParam) currentParam;
     211                                                PrimitiveParam<?> vp = (PrimitiveParam<?>) currentParam;
    212212                                                int setFlag = access.set(vp, pair.value);
    213213                                                if ((setFlag & Flags.PSET_HITMIN) != 0) {
     
    240240        }
    241241
    242         private static Exception createBoundaryHitException(AccessInterface access, PrimitiveParam param, String value, int flag) {
     242        private static Exception createBoundaryHitException(AccessInterface access, PrimitiveParam<?> param, String value, int flag) {
    243243                boolean minimum = (flag & Flags.PSET_HITMIN) != 0;
    244244                String boundary = (minimum ? param.getMin(Object.class) : param.getMax(Object.class)).toString();
  • java/main/src/main/java/com/framsticks/parsers/F0Writer.java

    r85 r87  
    4949                        }
    5050                        Object value = access.get(param, Object.class);
    51                         if (omitDefaults && (param instanceof PrimitiveParam) && Misc.equals(value, ((PrimitiveParam) param).getDef(Object.class))) {
     51                        if (omitDefaults && (param instanceof PrimitiveParam) && Misc.equals(value, ((PrimitiveParam<?>) param).getDef(Object.class))) {
    5252                                contiguous = false;
    5353                                continue;
  • java/main/src/main/java/com/framsticks/parsers/GenotypeLoader.java

    r85 r87  
    1313        public GenotypeLoader() throws Exception {
    1414
    15                 FramsClass entries = new FramsClass("Genotype", "org", "A Genotype with the associated performance information. All but one Genotype objects are placed in Genotype Groups. There is also a single static Genotype object not associated with a group, which is used as a temporary storage by genetic operators and some functions from GenePools.");
    16                 entries
    17                         .appendGroup(new Group("Body"))
    18                         .appendGroup(new Group("Performance"))
    19                         .appendGroup(new Group("Fitness"))
    20                         .appendGroup(new Group("Conversions"));
     15                FramsClass entries = FramsClass.build()
     16                        .name("Genotype")
     17                        .id("org")
     18                        .description("A Genotype with the associated performance information. All but one Genotype objects are placed in Genotype Groups. There is also a single static Genotype object not associated with a group, which is used as a temporary storage by genetic operators and some functions from GenePools.")
     19                        .group("Body")
     20                        .group("Performance")
     21                        .group("Fitness")
     22                        .group("Conversions")
     23                        .param(Param.build().id("name").group(0).name("Name").type(StringParam.class).min(0).max(40))
     24                        .param(Param.build().id("genotype").group(0).name("Genotype").type(StringParam.class).min(1))
     25                        .param(Param.build().id("info").group(0).name("Info").type(StringParam.class).min(1).help("Additional information or comments"))
     26                        .param(Param.build().id("simi").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Similarity").type(FloatParam.class))
     27                        .param(Param.build().id("energ0").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Starting energy").type(FloatParam.class))
     28                        .param(Param.build().id("strsiz").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Body parts (deprecated; use numparts)").type(FloatParam.class))
     29                        .param(Param.build().id("strjoints").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Body joints (deprecated; use numjoints)").type(FloatParam.class))
     30                        .param(Param.build().id("nnsiz").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Brain size (deprecated; use numneurons)").type(FloatParam.class))
     31                        .param(Param.build().id("nncon").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Brain connections (deprecated; use numconnections)").type(FloatParam.class))
     32                        .param(Param.build().id("numparts").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Body parts").type(FloatParam.class))
     33                        .param(Param.build().id("numjoints").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Body joints").type(FloatParam.class))
     34                        .param(Param.build().id("numneurons").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Brain size").type(FloatParam.class))
     35                        .param(Param.build().id("numconnections").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Brain connections").type(FloatParam.class))
     36                        .param(Param.build().id("num").group(2).name("Ordinal number").type(DecimalParam.class))
     37                        .param(Param.build().id("gnum").group(2).name("Generation").type(DecimalParam.class))
     38                        .param(Param.build().id("popsiz").group(2).flags(Flags.USERHIDDEN).name("Deprecated; use entities").type(DecimalParam.class))
     39                        .param(Param.build().id("entities").group(2).flags(Flags.DONTSAVE).name("Instances").type(DecimalParam.class).help("Copies of this genotype"))
     40                        .param(Param.build().id("lifespan").group(2).name("Life span").type(FloatParam.class).help("Average life span"))
     41                        .param(Param.build().id("velocity").group(2).name("Velocity").type(FloatParam.class).help("Average velocity"))
     42                        .param(Param.build().id("distance").group(2).name("Distance").type(FloatParam.class))
     43                        .param(Param.build().id("vertvel").group(2).name("Vertical velocity").type(FloatParam.class))
     44                        .param(Param.build().id("vertpos").group(2).name("Vertical position").type(FloatParam.class))
     45                        .param(Param.build().id("fit").group(3).flags(Flags.READONLY | Flags.DONTSAVE).name("Fitness").type(FloatParam.class))
     46                        .param(Param.build().id("fit2").group(3).flags(Flags.READONLY | Flags.DONTSAVE).name("Final fitness").type(FloatParam.class).help("Fitness shifted by (avg-n*stddev)"))
     47                        .param(Param.build().id("f0genotype").group(4).flags(Flags.READONLY | Flags.DONTSAVE).name("f0 genotype").type(StringParam.class).min(1).help("converted to f0 genotype"))
     48                        .param(Param.build().id("user1").group(2).name("User field 1").type(UniversalParam.class))
     49                        .param(Param.build().id("user2").group(2).name("User field 2").type(UniversalParam.class))
     50                        .param(Param.build().id("user3").group(2).name("User field 3").type(UniversalParam.class))
     51                        .param(Param.build().id("isValid").group(0).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Valid").type(DecimalParam.class).min(0).max(1))
     52                        .param(Param.build().id("uid").group(0).flags(Flags.READONLY | Flags.USERHIDDEN).name("#").type("s").help("Unique identifier"))
     53                        .finish();
    2154
    22                 //getId, group-number, getFlags, getName, getType(getType min max), getHelp
    23                 entries
    24                         .append(Param.build().id("name").group(0).name("Name").type(StringParam.class).min(0).max(40))
    25                         .append(Param.build().id("genotype").group(0).name("Genotype").type(StringParam.class).min(1))
    26                         .append(Param.build().id("info").group(0).name("Info").type(StringParam.class).min(1).help("Additional information or comments"))
    27                         .append(Param.build().id("simi").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Similarity").type(FloatParam.class))
    28                         .append(Param.build().id("energ0").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Starting energy").type(FloatParam.class))
    29                         .append(Param.build().id("strsiz").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Body parts (deprecated; use numparts)").type(FloatParam.class))
    30                         .append(Param.build().id("strjoints").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Body joints (deprecated; use numjoints)").type(FloatParam.class))
    31                         .append(Param.build().id("nnsiz").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Brain size (deprecated; use numneurons)").type(FloatParam.class))
    32                         .append(Param.build().id("nncon").group(1).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Brain connections (deprecated; use numconnections)").type(FloatParam.class))
    33                         .append(Param.build().id("numparts").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Body parts").type(FloatParam.class))
    34                         .append(Param.build().id("numjoints").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Body joints").type(FloatParam.class))
    35                         .append(Param.build().id("numneurons").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Brain size").type(FloatParam.class))
    36                         .append(Param.build().id("numconnections").group(1).flags(Flags.READONLY | Flags.DONTSAVE).name("Brain connections").type(FloatParam.class))
    37                         .append(Param.build().id("num").group(2).name("Ordinal number").type(DecimalParam.class))
    38                         .append(Param.build().id("gnum").group(2).name("Generation").type(DecimalParam.class))
    39                         .append(Param.build().id("popsiz").group(2).flags(Flags.USERHIDDEN).name("Deprecated; use entities").type(DecimalParam.class))
    40                         .append(Param.build().id("entities").group(2).flags(Flags.DONTSAVE).name("Instances").type(DecimalParam.class).help("Copies of this genotype"))
    41                         .append(Param.build().id("lifespan").group(2).name("Life span").type(FloatParam.class).help("Average life span"))
    42                         .append(Param.build().id("velocity").group(2).name("Velocity").type(FloatParam.class).help("Average velocity"))
    43                         .append(Param.build().id("distance").group(2).name("Distance").type(FloatParam.class))
    44                         .append(Param.build().id("vertvel").group(2).name("Vertical velocity").type(FloatParam.class))
    45                         .append(Param.build().id("vertpos").group(2).name("Vertical position").type(FloatParam.class))
    46                         .append(Param.build().id("fit").group(3).flags(Flags.READONLY | Flags.DONTSAVE).name("Fitness").type(FloatParam.class))
    47                         .append(Param.build().id("fit2").group(3).flags(Flags.READONLY | Flags.DONTSAVE).name("Final fitness").type(FloatParam.class).help("Fitness shifted by (avg-n*stddev)"))
    48                         .append(Param.build().id("f0genotype").group(4).flags(Flags.READONLY | Flags.DONTSAVE).name("f0 genotype").type(StringParam.class).min(1).help("converted to f0 genotype"))
    49                         .append(Param.build().id("user1").group(2).name("User field 1").type(UniversalParam.class))
    50                         .append(Param.build().id("user2").group(2).name("User field 2").type(UniversalParam.class))
    51                         .append(Param.build().id("user3").group(2).name("User field 3").type(UniversalParam.class))
    52                         .append(Param.build().id("isValid").group(0).flags(Flags.READONLY | Flags.DONTSAVE | Flags.USERHIDDEN).name("Valid").type(DecimalParam.class).min(0).max(1))
    53                         .append(Param.build().id("uid").group(0).flags(Flags.READONLY | Flags.USERHIDDEN).name("#").type("s").help("Unique identifier"));
    54 
    55                 ReflectionAccess reflectionParam = new ReflectionAccess(Genotype.class, entries);
     55                AccessInterface reflectionParam = new PropertiesAccess(entries);
    5656                addAccessInterface(reflectionParam);
    5757                addBreakCondition(Status.AfterObject);
  • java/main/src/main/java/com/framsticks/parsers/Loaders.java

    r86 r87  
    1212
    1313        public static FramsClass loadFramsClass(SourceInterface source) throws ConstructionException {
    14                 MultiParamLoader loader = new MultiParamLoader();
     14                final MultiParamLoader loader = new MultiParamLoader();
    1515                loader.setNewSource(source);
    1616
    17                 FramsClass result = new FramsClass();
     17                final FramsClassBuilder builder = FramsClass.build();
    1818
    19                 AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class, FramsClassBuilder.buildForClass(FramsClass.class));
    20                 AccessInterface paramBuilderAccess = new ReflectionAccess(ParamBuilder.class, FramsClassBuilder.buildForClass(ParamBuilder.class));
    21                 framsClassAccess.select(result);
     19                final AccessInterface framsClassAccess = new ReflectionAccess(FramsClassBuilder.class, FramsClass.build().forClass(FramsClassBuilder.class));
     20                AccessInterface paramBuilderAccess = new ReflectionAccess(ParamBuilder.class, FramsClass.build().forClass(ParamBuilder.class));
     21                framsClassAccess.select(builder);
    2222                loader.addAccessInterface(framsClassAccess);
    2323                loader.addAccessInterface(paramBuilderAccess);
    2424
    25                 loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
     25                loader.addListener(MultiParamLoader.Status.AfterObject, new MultiParamLoader.StatusListener() {
     26                        @Override
     27                        public void onStatusChange() {
     28                                Object object = loader.returnObject();
     29                                if (object instanceof FramsClassBuilder) {
     30                                        return;
     31                                }
     32                                if (framsClassAccess.select(builder).tryAutoAppend(object)) {
     33                                        return;
     34                                }
     35                                throw new ConstructionException().msg("failed to interpretate object").arg("object", object);
     36
     37                        }
     38                });
    2639
    2740                try {
    28                         MultiParamLoader.Status condition;
    29                         while ((condition = loader.go()) != MultiParamLoader.Status.Finished) {
    30                                 if (condition == MultiParamLoader.Status.AfterObject) {
    31 
    32                                         Object object = loader.returnObject();
    33                                         if (object instanceof FramsClass) {
    34                                                 continue;
    35                                         }
    36                                         if (object instanceof ParamBuilder) {
    37                                                 result.append(((ParamBuilder) object).finish());
    38                                         }
    39                                 }
    40                         }
    41                         return result;
     41                        loader.go();
     42                        return builder.finish();
    4243                } catch (Exception e) {
    4344                        throw new ConstructionException().msg("an error occurred while loading class description").arg("before", loader.getCurrentLine()).cause(e);
  • java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java

    r86 r87  
    99
    1010public class MultiParamLoader {
     11
     12        public interface StatusListener {
     13                void onStatusChange();
     14        }
     15
    1116        private final static Logger log = Logger.getLogger(MultiParamLoader.class);
    1217
     
    2732        }
    2833
     34        protected final Map<Status, List<StatusListener>> listeners = new HashMap<>();
     35
    2936        /**
    3037         * Specifies the action that should be taken inside loops.
     
    3643        protected AccessInterface lastAccessInterface;
    3744
     45        protected static FramsClass emptyFramsClass = FramsClass.build().idAndName("<empty>").finish();
    3846        /**
    3947         * Empty Param representing unknown classes - used to omit unknown
    4048         * objects in the file.
    4149         */
    42         protected AccessInterface emptyParam = new PropertiesAccess(new FramsClass());
     50        protected AccessInterface emptyParam = new PropertiesAccess(emptyFramsClass);
    4351
    4452        /**
     
    5765        private Status status = Status.None;
    5866
    59         private void setStatus(Status status) {
    60                 log.trace("changing status: " + this.status.toString() + " -> " + status.toString());
    61                 this.status = status;
    62         }
    6367
    6468        /**
     
    176180                        lastAccessInterface.load(currentSource);
    177181
    178                         if (isBreakCondition(Status.AfterObject)) {
    179                                 // break after object creation
     182                        if (changeStatus(Status.AfterObject)) {
    180183                                return LoopAction.Break;
    181184                        }
    182 
    183185                        return LoopAction.Continue;
    184186                } else if (status == Status.BeforeUnknown) {
     
    187189                        // found unknown object
    188190                        emptyParam.load(currentSource);
    189                         setStatus(Status.AfterObject);
    190 
     191                        if (changeStatus(Status.AfterObject)) {
     192                                return LoopAction.Break;
     193                        }
    191194                        return LoopAction.Continue;
    192195                }
     
    236239         */
    237240        private LoopAction isCommentLine(String line) {
    238                 if (line.charAt(0) == '#' && isBreakCondition(Status.OnComment)) {
    239                         // it's a simple comment - maybe we should break?
     241                if (line.charAt(0) == '#') {
    240242                        lastComment = line;
    241                         return LoopAction.Break;
    242                 }
    243 
     243                        if (changeStatus(Status.OnComment)) {
     244                                // it's a simple comment - maybe we should break?
     245                                return LoopAction.Break;
     246                        }
     247                }
    244248                return LoopAction.Nothing;
    245249        }
     
    255259
    256260                        if (lastAccessInterface != null) {
    257                                 if (isBreakCondition(Status.BeforeObject)) {
    258                                         log.debug("breaking before object");
     261                                if (changeStatus(Status.BeforeObject)) {
    259262                                        return LoopAction.Break;
    260263                                } else {
     
    263266                        } else {
    264267                                lastUnknownObjectName = typeName;
    265                                 if (isBreakCondition(Status.BeforeUnknown)) {
    266                                         log.debug("breaking before unknown");
     268                                if (changeStatus(Status.BeforeUnknown)) {
    267269                                        return LoopAction.Break;
    268270                                } else {
     
    309311                }
    310312
    311                 setStatus(Status.Finished);
     313                changeStatus(Status.Finished);
    312314        }
    313315
     
    320322
    321323                currentSource = source;
    322                 setStatus(Status.Loading);
     324                changeStatus(Status.Loading);
    323325
    324326                return true;
     
    391393         * Checks whether execution should break on selected condition.
    392394         */
    393         private boolean isBreakCondition(Status condition) {
    394                 setStatus(condition);
    395                 return breakConditions.contains(condition);
     395        private boolean changeStatus(Status status) {
     396                log.trace("changing status: " + this.status.toString() + " -> " + status.toString());
     397                this.status = status;
     398                if (listeners.containsKey(status)) {
     399                        for (StatusListener l : listeners.get(status)) {
     400                                l.onStatusChange();
     401                        }
     402                }
     403                return breakConditions.contains(status);
    396404        }
    397405
     
    405413                return result;
    406414        }
     415
     416        public void addListener(Status status, StatusListener listener) {
     417                if (!listeners.containsKey(status)) {
     418                        listeners.put(status, new LinkedList<StatusListener>());
     419                }
     420                listeners.get(status).add(listener);
     421        }
    407422}
  • java/main/src/main/java/com/framsticks/parsers/Schema.java

    r85 r87  
    88
    99import com.framsticks.params.*;
     10import com.framsticks.params.annotations.AutoAppendAnnotation;
     11import com.framsticks.params.annotations.FramsClassAnnotation;
     12import com.framsticks.util.FramsticksException;
    1013import com.framsticks.util.lang.Numbers;
    1114import org.apache.log4j.Logger;
     
    3033 * (please replace name and surname with my personal data)
    3134 */
     35@FramsClassAnnotation
    3236public class Schema {
    3337
     
    4246                //return new FileInputStream(new File(Schema.class.getResource("/parsers/f0def.xml").getPath()));
    4347                return Schema.class.getResourceAsStream("/parsers/f0def.xml");
     48        }
     49
     50        public Schema() {
     51        }
     52
     53        @AutoAppendAnnotation
     54        public void addNeuroClass(NeuroClass neuroClass) {
    4455        }
    4556
     
    5263         *             the exception if one occurred while reading the stream
    5364         */
    54         public Schema(InputStream inputStream) throws Exception {
     65        public Schema(InputStream inputStream) {
    5566
    5667                DocumentBuilderFactory factory;
     
    105116
    106117                } catch (IOException | ParserConfigurationException | SAXException e) {
    107                         logger.fatal("unexpected exception occurred: ", e);
    108                         throw e;
    109                 }
    110 
     118                        throw new FramsticksException().msg("unexpected exception occurred").cause(e);
     119                }
    111120        }
    112121
     
    170179         *             the exception in case of any error
    171180         */
    172         private static FramsClass processClass(Node classNode) throws Exception {
     181        private static FramsClass processClass(Node classNode) {
    173182                String classId = null;
    174183                String className = "";
    175184                String classDescription = "";
    176185                try {
    177                         classId = classNode.getAttributes().getNamedItem("ID")
    178                                         .getNodeValue();
     186                        classId = classNode.getAttributes().getNamedItem("ID").getNodeValue();
    179187                } catch (NullPointerException e) {
    180                         throw new Exception("Class getId is not defined!");
     188                        throw new FramsticksException().msg("class id is not defined");
    181189                }
    182190
     
    184192                classDescription = getAttributeFromNode("DESCRIPTION", classNode);
    185193
    186                 FramsClass framsClass = new FramsClass(classId, className, classDescription);
     194                FramsClassBuilder builder = FramsClass.build().id(classId).name(className).description(classDescription);
    187195
    188196                NodeList classProperties = classNode.getChildNodes();
     
    195203                                String name = getAttribute(attributes, "NAME");
    196204                                if (name == null) {
    197                                         logger.warn("Group name in class \"" + classId + "\" ("
    198                                                         + className + ") is undefined");
     205                                        logger.warn("Group name in class \"" + classId + "\" (" + className + ") is undefined");
    199206                                } else {
    200                                         framsClass.appendGroup(new Group(name));
     207                                        builder.group(new Group(name));
    201208                                }
    202209                        } else if ("PROP".equals(node.getNodeName())
     
    204211
    205212                                NamedNodeMap attributes = node.getAttributes();
    206                                 Param param = processParameter(attributes, classId);
    207                                 framsClass.append(param);
     213                                processParameter(attributes, classId, builder);
    208214                        }
    209215
    210216                }
    211217
    212                 return framsClass;
     218                return builder.finish();
    213219        }
    214220
     
    231237         *             the exception in case of any error
    232238         */
    233         private static Param processParameter(NamedNodeMap attributes, String classId)
    234                         throws Exception {
     239        private static void processParameter(NamedNodeMap attributes, String classId, FramsClassBuilder classBuilder) {
    235240
    236241                String id = getAttribute(attributes, "ID");
    237                 if (id == null)
    238                         throw new Exception("Property ID in class \"" + classId
    239                                         + "\" is undefined");
     242                if (id == null) {
     243                        throw new FramsticksException().msg("Property ID in class \"" + classId + "\" is undefined");
     244                }
    240245                String type = getAttribute(attributes, "TYPE");
    241                 if (type == null)
    242                         throw new Exception("TYPE of property \"" + id + "\" is undefined");
     246                if (type == null) {
     247                        throw new FramsticksException().msg("TYPE of property \"" + id + "\" is undefined");
     248                }
    243249
    244250                String name = getAttribute(attributes, "NAME");
     
    261267                }
    262268
    263                 ParamBuilder builder = Param.build();
    264                 builder.id(id).name(name).help(description).group(group).flags(flags);
     269                ParamBuilder builder = classBuilder.param(id).name(name).help(description).group(group).flags(flags);
    265270
    266271                builder.type(type);
     
    282287                        builder.type(type);
    283288                }
    284                 return builder.finish();
     289
     290                classBuilder.param(builder);
    285291        }
    286292
  • java/main/src/main/java/com/framsticks/remote/RemoteInstance.java

    r85 r87  
    124124        }
    125125
     126        public void setAddress(String address) {
     127                setConnection(new ClientConnection(address));
     128        }
    126129
    127130        public void setConnection(ClientConnection connection) {
     
    372375                                                loader.setNewSource(files.get(0).getContent());
    373376                                                loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
    374                                                 ReflectionAccess access = new ReflectionAccess(ListChange.class, ListChange.getFramsClass());
     377                                                ReflectionAccess access = new ReflectionAccess(ListChange.class, FramsClass.build().forClass(ListChange.class));
    375378                                                loader.addAccessInterface(access);
    376379                                                MultiParamLoader.Status status;
  • java/main/src/main/java/com/framsticks/util/FramsticksException.java

    r86 r87  
    3535        }
    3636
     37        @Override
    3738        public String getMessage() {
    3839                StringBuilder b = new StringBuilder();
     
    4950                        b.append("(").append(d.build()).append(")");
    5051                }
     52                if (this.getCause() instanceof FramsticksException) {
     53                        b.append(" caused by ").append(this.getCause().getMessage());
     54                }
    5155                return b.toString();
    5256        }
  • java/main/src/main/java/com/framsticks/util/lang/Numbers.java

    r84 r87  
    99
    1010        @SuppressWarnings("unchecked")
    11         public static <T extends Number> T parse(String value, Class<T> type) {
     11        public static <T> T parse(String value, Class<T> type) {
    1212                if (!Strings.notEmpty(value)) {
    1313                        return null;
     
    3030        }
    3131
     32        // @SuppressWarnings("unchecked")
     33        // public static <T> T parse(String value, Class<T> type) {
     34        //      return null;
     35        // }
    3236
    3337
  • java/main/src/main/java/com/framsticks/util/lang/Pair.java

    r86 r87  
    1818        }
    1919
     20        @Override
     21        public boolean equals(Object obj) {
     22                if (!(obj instanceof Pair)) {
     23                        return false;
     24                }
     25                Pair<?, ?> p = (Pair<?, ?>) obj;
     26                // return first == p.first && second.equals(se)
     27                return first.equals(p.first) && second.equals(p.second);
     28        }
     29
     30        @Override
     31        public int hashCode() {
     32                return (first != null ? first.hashCode() : 0) ^ (second != null ? second.hashCode() : 0);
     33        }
     34
    2035}
  • java/main/src/test/java/com/framsticks/gui/BrowserTest.java

    r84 r87  
    1414import org.testng.annotations.*;
    1515
    16 import com.framsticks.communication.ClientConnection;
    1716import com.framsticks.remote.RemoteInstance;
    1817import com.framsticks.test.TestConfiguration;
     
    4241                RemoteInstance localhost = new RemoteInstance();
    4342                localhost.setName("localhost");
    44                 localhost.setConnection(new ClientConnection("localhost:9009"));
     43                localhost.setAddress("localhost:9009");
    4544
    4645                browser.addEndpointForInstance(localhost);
  • java/main/src/test/java/com/framsticks/model/CreatureTest.java

    r86 r87  
    44
    55import com.framsticks.params.FramsClass;
    6 import com.framsticks.params.FramsClassBuilder;
    76import com.framsticks.params.ReflectionAccess;
    87import com.framsticks.params.types.ArrayListParam;
     
    2322        @Test
    2423        public void testFramsClass() {
    25                 framsClass = FramsClassBuilder.buildForClass(Creature.class);
     24                framsClass = FramsClass.build().forClass(Creature.class);
    2625
    2726                assertThat(framsClass).describedAs("framsClass").isNotNull();
     
    3534        }
    3635
    37         @Test
     36        @Test(dependsOnMethods = "testFramsClass")
    3837        public void testReflectionAccess() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    3938                access = new ReflectionAccess(Creature.class, framsClass);
  • java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java

    r86 r87  
    1818        @Test
    1919        public void createBuilderFramsClass() {
    20                 builderFramsClass = FramsClassBuilder.buildForClass(ParamBuilder.class);
     20                builderFramsClass = FramsClass.build().forClass(ParamBuilder.class);
    2121
    2222                assertThat(builderFramsClass.getParamCount()).isEqualTo(6);
  • java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java

    r84 r87  
    22
    33import org.testng.annotations.*;
     4
    45import com.framsticks.model.*;
    56import com.framsticks.model.Package;
    67import com.framsticks.params.*;
    78import com.framsticks.params.types.FloatParam;
     9import com.framsticks.params.types.StringParam;
    810import com.framsticks.test.TestConfiguration;
    911import com.framsticks.util.math.Point3d;
     
    3436        public void primitiveParam() {
    3537                FramsClass joint = schema.getRegistry().getInfoFromCache("j");
    36                 PrimitiveParam dx = joint.getParamEntry("dx", PrimitiveParam.class);
     38                PrimitiveParam<?> dx = joint.getParamEntry("dx", PrimitiveParam.class);
    3739                assertThat(dx).isInstanceOf(FloatParam.class);
    3840                assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
    3941                assertThat(dx.getName()).isEqualTo("delta.x");
    4042                assertThat(dx.getMin(Double.class)).isEqualTo(-2.0, delta(0.0));
     43
     44                assertThat(schema.getRegistry().getInfoFromCache("n").getParamEntry("d", StringParam.class).getDef(String.class)).isEqualTo("N");
    4145        }
    4246
Note: See TracChangeset for help on using the changeset viewer.