View Javadoc
1   package ordertracker;
2   
3   import com.google.common.base.MoreObjects;
4   import com.google.common.base.Optional;
5   import com.google.common.collect.Sets;
6   import java.io.Serializable;
7   import java.lang.Class;
8   import java.lang.Double;
9   import java.lang.IllegalAccessException;
10  import java.lang.IllegalArgumentException;
11  import java.lang.InstantiationException;
12  import java.lang.NullPointerException;
13  import java.lang.Override;
14  import java.lang.SecurityException;
15  import java.lang.String;
16  import java.lang.SuppressWarnings;
17  import java.lang.System;
18  import java.lang.reflect.InvocationTargetException;
19  import java.math.BigDecimal;
20  import java.util.Set;
21  import java.util.concurrent.TimeUnit;
22  import java.util.regex.Pattern;
23  import javax.persistence.CascadeType;
24  import javax.persistence.Column;
25  import javax.persistence.Entity;
26  import javax.persistence.EntityManager;
27  import javax.persistence.FetchType;
28  import javax.persistence.Id;
29  import javax.persistence.OneToMany;
30  import javax.persistence.PrePersist;
31  import javax.persistence.PreUpdate;
32  import javax.persistence.Table;
33  import javax.persistence.Transient;
34  import ordertracker.Order;
35  import scala.concurrent.duration.Duration;
36  import xuml.tools.model.compiler.runtime.BehaviourFactoryNotSetException;
37  import xuml.tools.model.compiler.runtime.CreationEvent;
38  import xuml.tools.model.compiler.runtime.EntityHelper;
39  import xuml.tools.model.compiler.runtime.Event;
40  import xuml.tools.model.compiler.runtime.Signaller;
41  import xuml.tools.model.compiler.runtime.ValidationException;
42  import xuml.tools.model.compiler.runtime.query.BooleanExpression;
43  import xuml.tools.model.compiler.runtime.query.NumericExpressionField;
44  import xuml.tools.model.compiler.runtime.query.SelectBuilder;
45  import xuml.tools.model.compiler.runtime.query.StringExpressionField;
46  
47  /**
48   * 
49   */
50  @Entity
51  @Table(schema="ordertracker", name="depot")
52  public class Depot implements xuml.tools.model.compiler.runtime.Entity<Depot> {
53  
54      /**
55       * No argument constructor required by JPA.
56       */
57      public Depot(){
58          //JPA requires no-arg constructor
59          if (_behaviourFactory == null) {
60              throw new BehaviourFactoryNotSetException("Depot does not have a BehaviourFactory set. Use Depot.setBehaviourFactory in your App class (one-time setup).");
61          }
62          _behaviour = _behaviourFactory.create(this);
63      }
64  
65      /**
66       * If behaviour is not explicitly specified then the
67       * behaviour factory is used to create behaviour.
68       */
69      private static volatile BehaviourFactory _behaviourFactory;
70  
71      /**
72       * All actions like onEntry actions and defined
73       * operations are performed by this Behaviour class.
74       */
75      @Transient
76      private Behaviour _behaviour;
77  
78      /**
79       * Sets the BehaviourFactory for all instances of
80       * this class. It will only be used when Behaviour
81       * is not explicitly provided in the constructor.
82       */
83      public static void setBehaviourFactory(BehaviourFactory factory){
84          _behaviourFactory = factory;
85      }
86  
87      /**
88       * Sets the BehaviourFactory for all instances of
89       * this class using the given Behaviour class as the base. It will only be used when Behaviour
90       * is not explicitly provided in the constructor.
91       */
92      public static void setBehaviourFactory(Class<? extends Behaviour> cls){
93          _behaviourFactory = createBehaviourFactory(cls);
94      }
95  
96      /**
97       * Returns the singleton BehaviourFactory for this.
98       */
99      public static BehaviourFactory getBehaviourFactory(){
100         return _behaviourFactory;
101     }
102 
103     /**
104      * Constructor using id.
105      */
106     public Depot(String id) {
107         this.id = id;
108     }
109 
110     /**
111      * Static creator method using id.
112      */
113     public static Depot create(String id) {
114         return new Depot(id);
115     }
116 
117     /**
118      * Static creator method using CreationEvent.
119      */
120     public static Depot create(CreationEvent<Depot> creationEvent) {
121         return Context.create(Depot.class, creationEvent);
122     }
123 
124     /**
125      * The signaller used by the current Context. It will
126      * get injected into the EntityHelper.
127      */
128     private static Signaller signaller;
129 
130     /**
131      * Sets the Signaller to be used by the EntityHelper.
132      */
133     static void setSignaller_(Signaller sig) {
134         signaller = sig;
135     }
136 
137     /**
138      * Helper for this class.
139      */
140     @Transient
141     private EntityHelper _helper;
142 
143     /**
144      * Returns the Helper for this instance.
145      */
146     public synchronized EntityHelper helper() {
147         if (_helper==null)
148             _helper = new EntityHelper(signaller,this);
149         return _helper;
150     }
151 
152     /**
153      * Primary identifier
154      */
155     @Id
156     @Column(name="depot_id", nullable=false,length=2048)
157     private String id = new String("");
158 
159     /**
160      * Returns a unique id for this instance as a String. 
161      * Used for synchronizing access to entities.
162      */
163     @Override
164     public String uniqueId(){
165         return Depot.class.getName() + ":" + getId();
166     }
167 
168     @Column(name="name_1", nullable=false,length=255)
169     private String name = new String("");
170 
171     /**
172      * Validates name against type constraints.
173      */
174     private void validateName() {
175         if (name == null || name.length() < 1)
176             throw new ValidationException("min length constraint not met");
177          if (name == null || !name.startsWith(""))
178             throw new ValidationException("prefix constraint not met");
179         if (name == null || !name.endsWith(""))
180             throw new ValidationException("suffix constraint not met");
181         if (name == null || !Pattern.matches(".*", name))
182             throw new ValidationException("validation pattern constraint not met");
183     }
184 
185     @Column(name="latitude", nullable=false,precision=20)
186     private Double latitude = new Double("0");
187 
188     private static final BigDecimal LATITUDE_UPPER_LIMIT=new BigDecimal("90");
189     private static final BigDecimal LATITUDE_LOWER_LIMIT=new BigDecimal("-90");
190 
191     /**
192      * Validates latitude against type constraints.
193      */
194     private void validateLatitude() {
195         if (LATITUDE_UPPER_LIMIT.doubleValue() < latitude) 
196             throw new ValidationException("upper limit of 90 failed");
197         if (LATITUDE_LOWER_LIMIT.doubleValue() > latitude)
198              throw new ValidationException("lower limit of -90 failed");
199     }
200 
201     @Column(name="longitude", nullable=false,precision=20)
202     private Double longitude = new Double("0");
203 
204     private static final BigDecimal LONGITUDE_UPPER_LIMIT=new BigDecimal("180");
205     private static final BigDecimal LONGITUDE_LOWER_LIMIT=new BigDecimal("-180");
206 
207     /**
208      * Validates longitude against type constraints.
209      */
210     private void validateLongitude() {
211         if (LONGITUDE_UPPER_LIMIT.doubleValue() < longitude) 
212             throw new ValidationException("upper limit of 180 failed");
213         if (LONGITUDE_LOWER_LIMIT.doubleValue() > longitude)
214              throw new ValidationException("lower limit of -180 failed");
215     }
216 
217     /**
218      * For internal use only by the state machine but is persisted by the jpa provider.
219      */
220     @Column(name="state",nullable=false)
221     private String state;
222 
223     /**
224      * ZERO_ONE Depot is last location of MANY Order
225      */
226     @OneToMany(mappedBy="depot_R1", cascade=CascadeType.ALL, fetch=FetchType.LAZY, targetEntity=Order.class)
227     private Set<Order> order_R1 = Sets.newHashSet();
228 
229     /**
230      * Getter. ZERO_ONE Depot is last location of MANY Order
231      */
232     public Set<Order> getOrder_R1(){
233         return order_R1;
234     }
235 
236     /**
237      * Setter. ZERO_ONE Depot is last location of MANY Order
238      */
239     public void setOrder_R1(Set<Order> order_R1){
240         this.order_R1=order_R1;
241     }
242 
243     /**
244      * ZERO_ONE Depot is last location of MANY Order
245      */
246     public Depot relateAcrossR1(Order order_R1) {
247         order_R1.setDepot_R1(this);
248         return this;
249     }
250 
251     /**
252      * ZERO_ONE Depot is last location of MANY Order
253      */
254     public Depot unrelateAcrossR1(Order order_R1) {
255         getOrder_R1().remove(order_R1);
256         order_R1.setDepot_R1(null);
257         return this;
258     }
259 
260     /**
261      * Calls all validation methods just before updating database.
262      */
263     @PreUpdate
264     void validateBeforeUpdate(){
265         validateLatitude();
266         validateLongitude();
267         validateName();
268     }
269 
270     /**
271      * Calls all validation methods just before first persist of this entity.
272      */
273     @PrePersist
274     void validateBeforePersist(){
275         validateLatitude();
276         validateLongitude();
277         validateName();
278     }
279 
280     /**
281      * Returns the identifier for this entity.
282      */
283     public String getId() {
284         return id;
285     }
286 
287     public void setId(String id) {
288         this.id = id;
289     }
290 
291     public Depot setId_(String id) {
292         this.id = id;
293         return this;
294     }
295 
296     /**
297      * Returns name. 
298      */
299     public String getName(){
300         return name;
301     }
302 
303     /**
304      * Sets name to the given value. 
305      */
306     public void setName(String name){
307         this.name = name;
308     }
309 
310     /**
311      * Sets the attribute to the given value and returns this
312      * (enables method chaining).
313      */
314     public Depot setName_(String name){
315         setName(name);
316         return this;
317     }
318 
319     /**
320      * Returns latitude. 
321      */
322     public Double getLatitude(){
323         return latitude;
324     }
325 
326     /**
327      * Sets latitude to the given value. 
328      */
329     public void setLatitude(Double latitude){
330         this.latitude = latitude;
331     }
332 
333     /**
334      * Sets the attribute to the given value and returns this
335      * (enables method chaining).
336      */
337     public Depot setLatitude_(Double latitude){
338         setLatitude(latitude);
339         return this;
340     }
341 
342     /**
343      * Returns longitude. 
344      */
345     public Double getLongitude(){
346         return longitude;
347     }
348 
349     /**
350      * Sets longitude to the given value. 
351      */
352     public void setLongitude(Double longitude){
353         this.longitude = longitude;
354     }
355 
356     /**
357      * Sets the attribute to the given value and returns this
358      * (enables method chaining).
359      */
360     public Depot setLongitude_(Double longitude){
361         setLongitude(longitude);
362         return this;
363     }
364 
365     /**
366      * For internal use only by the state machine but is persisted by the jpa provider.
367      */
368     public String getState(){
369         return state;
370     }
371 
372     /**
373      * For internal use only by the state machine but is persisted by the jpa provider.
374      */
375     public void setState(String state){
376         this.state = state;
377     }
378 
379     /**
380      * Sets the current state. This should only be used when creating an instance without using the state machine.
381      */
382     public void setState(State state){
383         this.state = state.toString();
384     }
385 
386     /**
387      * The list of all states from the state machine for this entity.
388      */
389     public static enum State {
390         CREATED;
391     }
392 
393     /**
394      * Event declarations.
395      */
396     public static class Events {
397 
398         /**
399          * Event implementation for event 'Create'
400          */
401         @SuppressWarnings("serial")
402         public static class Create implements Event<Depot>, Serializable, CreationEvent<Depot> {
403 
404             public static final String signatureKey = "java.lang.String;java.lang.String;java.lang.Double;java.lang.Double;";
405 
406             public String signatureKey() {
407                 return signatureKey;
408             }
409             private final String depotID;
410             private final String name;
411             private final Double latitudet;
412             private final Double longitude;
413 
414             /**
415              * Constructor.
416              */
417             public Create(String depotID, String name, Double latitudet, Double longitude){
418                 if (depotID == null) throw new NullPointerException("depotID cannot be null");
419                 this.depotID = depotID;
420                 if (name == null) throw new NullPointerException("name cannot be null");
421                 this.name = name;
422                 if (latitudet == null) throw new NullPointerException("latitudet cannot be null");
423                 this.latitudet = latitudet;
424                 if (longitude == null) throw new NullPointerException("longitude cannot be null");
425                 this.longitude = longitude;
426             }
427 
428             public String getDepotID(){
429                 return depotID;
430             }
431 
432             public String getName(){
433                 return name;
434             }
435 
436             public Double getLatitudet(){
437                 return latitudet;
438             }
439 
440             public Double getLongitude(){
441                 return longitude;
442             }
443 
444             private Create(Builder builder) {
445                 if (builder.depotID == null) throw new NullPointerException("depotID cannot be null");
446                 this.depotID = builder.depotID;
447                 if (builder.name == null) throw new NullPointerException("name cannot be null");
448                 this.name = builder.name;
449                 if (builder.latitudet == null) throw new NullPointerException("latitudet cannot be null");
450                 this.latitudet = builder.latitudet;
451                 if (builder.longitude == null) throw new NullPointerException("longitude cannot be null");
452                 this.longitude = builder.longitude;
453             }
454 
455             public static Builder builder() {
456                 return new Builder();
457             }
458 
459             public static class Builder {
460 
461                 private String depotID;
462                 private String name;
463                 private Double latitudet;
464                 private Double longitude;
465 
466                 public Builder depotID(String depotID) {
467                     this.depotID = depotID;
468                     return this;
469                 }
470 
471                 public Builder name(String name) {
472                     this.name = name;
473                     return this;
474                 }
475 
476                 public Builder latitudet(Double latitudet) {
477                     this.latitudet = latitudet;
478                     return this;
479                 }
480 
481                 public Builder longitude(Double longitude) {
482                     this.longitude = longitude;
483                     return this;
484                 }
485 
486                 public Create build() {
487                     return new Create(this);
488                 }
489             }
490 
491             @Override
492             public String toString() {
493                 return MoreObjects.toStringHelper(this.getClass())
494                     .add("depotID", depotID)
495                     .add("name", name)
496                     .add("latitudet", latitudet)
497                     .add("longitude", longitude)
498                     .toString();
499             }
500         }
501 
502     }
503 
504     /**
505      * Asychronously queues the given signal against this entity for processing.
506      */
507     @Override
508     public Depot signal(Event<Depot> event) {
509         helper().signal(event);
510         return this;
511     }
512 
513     /**
514      * Asychronously queues the given signal against this entity for processing
515      * after the delay specified. Delay cannot be null.
516      */
517     @Override
518     public Depot signal(Event<Depot> event, Duration delay) {
519         helper().signal(event, Optional.of(delay));
520         return this;
521     }
522 
523     /**
524      * Asychronously queues the given signal against this entity for processing
525      * at the epoch time in ms specified. Delay cannot be null.
526      */
527     @Override
528     public Depot signal(Event<Depot> event, long time) {
529         return signal(event, Duration.create(time-System.currentTimeMillis(),TimeUnit.MILLISECONDS));
530     }
531 
532     public Depot cancelSignal(String eventSignatureKey) {
533          return this;
534     }
535 
536     public Depot cancelSignal(Event<Depot> event) {
537          return cancelSignal(event.signatureKey());
538     }
539 
540     /**
541      * Synchronously runs the on entry procedure associated
542      * with this event and also any signals to self that are
543      * made during the procedure. This method should not
544      * be called directly except in a unit testing scenario
545      * perhaps. Call signal method instead.
546      */
547     @Override
548     public Depot event(Event<Depot> event){
549 
550         helper().beforeEvent();
551 
552         // process the event
553         if (event instanceof Events.Create){
554             processEvent((Events.Create) event);
555         }
556 
557         helper().afterEvent();
558         return this;
559     }
560 
561     /**
562      * Synchronously perform the change.
563      */
564     private void processEvent(Events.Create event){
565         if (state==null){
566             state=State.CREATED.toString();
567             synchronized(this) {
568                 _behaviour.onEntryCreated(event);
569             }
570         }
571     }
572 
573     /**
574      * Static creator method associated with the creation transition to 'Created' via event 'Create'.
575      */
576     public static Depot create(EntityManager em, CreationEvent<Depot> event) {
577         Depot entity = new Depot();
578         entity.event(event);
579         em.persist(entity);
580         return entity;
581     }
582 
583     /**
584      * Same as EntityManager.merge() except allows method chaining.
585      * Returns a new merged instance.
586      */
587     public Depot merge(EntityManager em) {
588         return em.merge(this);
589     }
590 
591     /**
592      * Same as EntityManager.persist() except allows method chaining. Returns this.
593      */
594     public Depot persist(EntityManager em) {
595         em.persist(this);
596         return this;
597     }
598 
599 
600     /**
601      * Same as {@code persist(Context.em())}. Returns this.
602      */
603     public Depot persist() {
604         Context.em().persist(this);
605         return this;
606     }
607 
608     /**
609      * Same as EntityManager.remove() except inverted to facilitate method chaining. Returns this.
610      */
611     public Depot remove(EntityManager em) {
612         em.remove(this);
613         return this;
614     }
615 
616     /**
617      * Same as EntityManager.remove() except inverted to facilitate method chaining. Returns this.
618      */
619     public Depot remove() {
620         Context.remove(this);
621         return this;
622     }
623 
624     /**
625      * Same as this.remove()
626      */
627     public Depot delete() {
628         return remove();
629     }
630 
631     /**
632      * Same as EntityManager.refresh() except inverted to facilitate method chaining. Returns this.
633      */
634     public Depot refresh(EntityManager em) {
635         em.refresh(this);
636         return this;
637     }
638 
639     /**
640      * Does a merge then a refresh and returns a new updated merged instance.
641      */
642     public Depot load(EntityManager em) {
643         return merge(em).refresh(em);
644     }
645 
646     public Depot load() {
647         return Context.load(this);
648     }
649 
650     /**
651      * On entry procedures for this entity.
652      */
653     public static interface Behaviour {
654 
655         void onEntryCreated(Events.Create event);
656 
657     }
658 
659     /**
660      * A factory that creates behaviour for a given entity.
661      */
662     public static interface BehaviourFactory {
663 
664         Behaviour create(Depot entity);
665 
666     }
667 
668     /**
669      * Returns a BehaviourFactory on the assumption that the given class
670      * has a single constructor with one parameter of type Depot.
671      */
672     public static BehaviourFactory createBehaviourFactory(final Class<? extends Behaviour> cls) {
673         return new BehaviourFactory() {
674             @Override
675             public Behaviour create(Depot entity) {
676                 if (cls.getConstructors().length != 1)
677                      throw new RuntimeException(
678                               "expected only one constructor in the Behaviour implementation");
679                 try {
680                     return (Behaviour) cls.getConstructors()[0].newInstance(entity);
681                 } catch (InstantiationException e) {
682                     throw new RuntimeException(e);
683                 } catch (IllegalAccessException e) {
684                     throw new RuntimeException(e);
685                 } catch (IllegalArgumentException e) {
686                     throw new RuntimeException(e);
687                 } catch (InvocationTargetException e) {
688                     throw new RuntimeException(e);
689                 } catch (SecurityException e) {
690                     throw new RuntimeException(e);
691                 }
692             }
693         };
694     }
695 
696     public static Optional<Depot> find(String id) {
697         if (Context.em()!=null) {
698             return Optional.fromNullable(Context.em().find(Depot.class,id));
699         } else {
700             EntityManager em = Context.createEntityManager();
701             try {
702                 Depot result = em.find(Depot.class,id);
703                 return Optional.fromNullable(result);
704             } finally {
705                 em.close();
706             }
707         }
708     }
709 
710     public static class Attribute {
711         public static final StringExpressionField<Depot> name = new StringExpressionField<Depot>(
712             new xuml.tools.model.compiler.runtime.query.Field("name"));
713         public static final NumericExpressionField<Depot> latitude = new NumericExpressionField<Depot>(
714             new xuml.tools.model.compiler.runtime.query.Field("latitude"));
715         public static final NumericExpressionField<Depot> longitude = new NumericExpressionField<Depot>(
716             new xuml.tools.model.compiler.runtime.query.Field("longitude"));
717         public static final StringExpressionField<Depot> id = new StringExpressionField<Depot>(
718             new xuml.tools.model.compiler.runtime.query.Field("id"));
719         public static final StringExpressionField<Depot> order_R1_id = new StringExpressionField<Depot>(
720             new xuml.tools.model.compiler.runtime.query.Field("order_R1.id"));
721     }
722 
723     public static SelectBuilder<Depot> select(BooleanExpression<Depot> where) {
724         return new SelectBuilder<Depot>(where).entityClass(Depot.class).info(signaller.getInfo());
725     }
726 
727     public static SelectBuilder<Depot> select() {
728         return select(null);
729     }
730 
731 }