View Javadoc
1   package xuml.tools.model.compiler;
2   
3   import java.io.PrintStream;
4   import java.util.List;
5   import java.util.Map;
6   import java.util.stream.Collectors;
7   
8   import org.apache.commons.io.output.ByteArrayOutputStream;
9   
10  import com.google.common.collect.Maps;
11  
12  import xuml.tools.model.compiler.info.MyEvent;
13  import xuml.tools.model.compiler.info.MyTransition;
14  
15  /**
16   * Generates entity behaviour class (java source code) containing on-entry
17   * procedures.
18   * 
19   * @author dave
20   * 
21   */
22  public class BehaviourImplementationWriter {
23  
24      private final ClassInfo info;
25      private final String behaviourFullClassName;
26      private final TypeRegisterister.html#TypeRegister">TypeRegister types = new TypeRegister();
27  
28      /**
29       * Constructor.
30       * 
31       * @param info
32       * @param behaviourFullClassName
33       */
34      public BehaviourImplementationWriter(ClassInfo info, String behaviourFullClassName) {
35          this.info = info;
36          this.behaviourFullClassName = behaviourFullClassName;
37      }
38  
39      /**
40       * Returns generated java source code for the implementation of the class
41       * name specified in the constructor of this class.
42       * 
43       * @return
44       */
45      public String generate() {
46          ByteArrayOutputStream bytes = new ByteArrayOutputStream();
47          try (PrintStream out = new PrintStream(bytes)) {
48              generate(out);
49          }
50          String result = bytes.toString().replace("<IMPORTS>",
51                  types.getImports(behaviourFullClassName).trim());
52          return result;
53      }
54  
55      /**
56       * Writes generated java source code to the given {@link PrintStream}.
57       * 
58       * @param out
59       */
60      private void generate(PrintStream out) {
61          String simpleClassName = Util.getSimpleClassName(behaviourFullClassName);
62          String packageName = Util.getPackage(behaviourFullClassName);
63          out.format("package %s;\n\n", packageName);
64          out.format("<IMPORTS>\n\n");
65          out.format("public class %s implements %s {\n\n",
66                  Util.getSimpleClassName(behaviourFullClassName),
67                  types.addType(info.getClassFullName() + ".Behaviour"));
68  
69          writeFields(out, simpleClassName);
70  
71          writeOnEntryMethods(out);
72  
73          writeFactory(out);
74  
75          out.format("}");
76      }
77  
78      /**
79       * Writes required fields to the PrintStream.
80       * 
81       * @param out
82       * @param simpleClassName
83       */
84      private void writeFields(PrintStream out, String simpleClassName) {
85          out.format("    private final %s self;\n\n", info.addType(info.getClassFullName()));
86  
87          out.format("    public %s(%s self) {\n", simpleClassName,
88                  types.addType(info.getClassFullName()));
89          out.format("        this.self = self;\n");
90          out.format("    }\n\n");
91      }
92  
93      /**
94       * Writes the onEntry procedure methods.
95       * 
96       * @param out
97       */
98      private void writeOnEntryMethods(PrintStream out) {
99          Map<String, MyEvent> stateEvent = Maps.newLinkedHashMap();
100         for (MyEvent event : info.getEvents()) {
101             if (event.getStateName() != null)
102                 stateEvent.put(event.getStateName(), event);
103         }
104         List<MyEvent> nonStateEvents = info.getEvents().stream()
105                 .filter(ev -> ev.getStateName() == null).collect(Collectors.toList());
106 
107         for (MyEvent event : stateEvent.values()) {
108             writeStateEventOnEntryMethod(out, event);
109         }
110 
111         for (MyEvent event : nonStateEvents) {
112             writeNonStateEventEntryMethods(out, event);
113         }
114     }
115 
116     private void writeNonStateEventEntryMethods(PrintStream out, MyEvent event) {
117         for (MyTransition transition : info.getTransitions()) {
118             // constraint is no event overloading
119             if (transition.getEventName().equals(event.getName())) {
120                 out.format("    @%s\n", types.addType(Override.class));
121                 out.format("    public void onEntry%s(%s event) {\n",
122                         Util.upperFirst(Util.toJavaIdentifier(transition.getToState())),
123                         types.addType(
124                                 info.getClassFullName() + ".Events." + event.getSimpleClassName()));
125                 out.format("        //TODO write implementation here\n");
126                 out.format("    };\n\n");
127             }
128         }
129     }
130 
131     private void writeStateEventOnEntryMethod(PrintStream out, MyEvent event) {
132         out.format("    @%s\n", types.addType(Override.class));
133         out.format("    public void onEntry%s(%s event) {\n",
134                 Util.upperFirst(Util.toJavaIdentifier(event.getStateName())),
135                 types.addType(info.getClassFullName() + ".Events."
136                         + event.getStateSignatureInterfaceSimpleName()));
137         out.format("        //TODO write implementation here\n");
138         out.format("    };\n\n");
139     }
140 
141     private void writeFactory(PrintStream out) {
142         out.format("    public static class Factory implements %s {\n",
143                 types.addType(info.getClassFullName() + ".BehaviourFactory"));
144         out.format("        @%s\n", types.addType(Override.class));
145         out.format("        public %s create(%s entity) {\n\n",
146                 types.addType(info.getClassFullName() + ".Behaviour"),
147                 types.addType(info.getClassFullName()));
148         out.format("            return new %s(entity);\n", types.addType(behaviourFullClassName));
149         out.format("        }\n");
150         out.format("    }\n\n");
151 
152         out.format("    private static Factory factory = new Factory();\n\n");
153 
154         out.format("    public static Factory factory() {\n");
155         out.format("        return factory;\n");
156         out.format("    }\n");
157     }
158 
159 }