One state to rule them all
authorChristos KK Loverdos <loverdos@gmail.com>
Fri, 28 Sep 2012 15:11:42 +0000 (18:11 +0300)
committerChristos KK Loverdos <loverdos@gmail.com>
Fri, 28 Sep 2012 15:11:42 +0000 (18:11 +0300)
20 files changed:
src/main/avro/aquarium-user-state.avdl
src/main/java/gr/grnet/aquarium/message/avro/gen/AquariumUserState.java
src/main/java/gr/grnet/aquarium/message/avro/gen/UserStateMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/WalletEntriesMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/WalletEntryMsg.java
src/main/scala/gr/grnet/aquarium/Aquarium.scala
src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala
src/main/scala/gr/grnet/aquarium/charging/ChargingBehavior.scala
src/main/scala/gr/grnet/aquarium/charging/ChargingService.scala
src/main/scala/gr/grnet/aquarium/charging/ContinuousChargingBehavior.scala
src/main/scala/gr/grnet/aquarium/charging/OnceChargingBehavior.scala
src/main/scala/gr/grnet/aquarium/charging/VMChargingBehavior.scala
src/main/scala/gr/grnet/aquarium/charging/state/UserAgreementHistoryModel.scala
src/main/scala/gr/grnet/aquarium/charging/state/UserStateBootstrap.scala [deleted file]
src/main/scala/gr/grnet/aquarium/charging/state/UserStateModel.scala
src/main/scala/gr/grnet/aquarium/message/avro/MessageFactory.scala
src/main/scala/gr/grnet/aquarium/message/avro/ModelFactory.scala
src/main/scala/gr/grnet/aquarium/store/memory/MemStoreProvider.scala
src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala
src/main/scala/gr/grnet/aquarium/util/json/JsonNames.scala

index d05a8f2..4b5c366 100644 (file)
@@ -95,16 +95,17 @@ protocol AquariumUserState {
     string sumOfCreditsToSubtract; // The credit amount generated for this wallet entry.
     string oldTotalCredits;
     string newTotalCredits;
-    long whenComputedMillis; // When the computation took place
-    long referenceStartMillis;
-    long referenceStopMillis;
+    long whenComputedMillis;   // When the computation took place
+    long referenceStartMillis; // start of period this entry refers to
+    long referenceStopMillis;  // end of period this entry refers to
     int billingYear;
     int billingMonth;
     int billingMonthDay;
     array<ChargeslotMsg> chargeslots; // The details of the credit computation
-    array<ResourceEventMsg> resourceEvents; // current is the last one
+    array<ResourceEventMsg> resourceEvents; // The events used to make this computation. The current is the last one
     ResourceTypeMsg resourceType;
     boolean isSynthetic = false;
+    boolean isForRealtimeCalc = false;
   }
 
   // convenient wrapper for a list of wallet entries
@@ -120,15 +121,16 @@ protocol AquariumUserState {
     union {string, null} parentOriginalID;
     union {string, null} parentInStoreID;
     boolean isFirst = false; // True only for the very first user state
+    boolean isForFullMonth = false; // True when computed as a reference for a month's billing state
     map<ResourcesChargingStateMsg> stateOfResources; // Map[ResourceTypeMsg.name.type, ]
     string totalCredits = "0";
     long latestUpdateMillis; // // last update of this working user state
     long latestResourceEventOccurredMillis;
     long billingPeriodOutOfSyncResourceEventsCounter = 0;
-    int billingYear;
-    int billingMonth;
+    int billingYear; // The billing year this snapshot refers to
+    int billingMonth; //  The billing month this year refers to
     int billingMonthDay;
-    boolean isFullBillingMonth = false;
+    UserAgreementHistoryMsg userAgreementHistory;
     array<WalletEntryMsg> walletEntries;
   }
 }
\ No newline at end of file
index 7e18a58..f3febb6 100644 (file)
@@ -7,7 +7,7 @@ package gr.grnet.aquarium.message.avro.gen;
 
 @SuppressWarnings("all")
 public interface AquariumUserState {
-  public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"AquariumUserState\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"types\":[{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[\"CronSpecTupleMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":\"EffectiveUnitPriceMsg\"}}]},{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[\"EffectivePriceTableMsg\",{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"PolicyMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"resourceMapping\",\"type\":{\"type\":\"map\",\"values\":\"ResourceTypeMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":\"FullPriceTableMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"DetailsMsg\",\"fields\":[{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementMsg\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"relatedIMEventOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"fullPriceTableRef\",\"type\":[\"FullPriceTableMsg\",\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[\"IMEventMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"ResourceInstanceChargingStateMsg\",\"fields\":[{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"previousEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"implicitlyIssuedStartEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"accumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldAccumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"previousValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"currentValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourcesChargingStateMsg\",\"fields\":[{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResourceInstance\",\"type\":{\"type\":\"map\",\"values\":\"ResourceInstanceChargingStateMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementHistoryMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"latestOccurredMillis\",\"type\":\"long\"},{\"name\":\"latestValidFromMillis\",\"type\":\"long\"},{\"name\":\"userCreationTimeMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"agreements\",\"type\":{\"type\":\"array\",\"items\":\"UserAgreementMsg\"}}]},{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]},{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":\"ChargeslotMsg\"}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":\"ResourceTypeMsg\"},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false}]},{\"type\":\"record\",\"name\":\"WalletEntriesMsg\",\"fields\":[{\"name\":\"entries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]},{\"type\":\"record\",\"name\":\"UserStateMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"parentOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentInStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"isFirst\",\"type\":\"boolean\",\"default\":false},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":\"ResourcesChargingStateMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"0\"},{\"name\":\"latestUpdateMillis\",\"type\":\"long\"},{\"name\":\"latestResourceEventOccurredMillis\",\"type\":\"long\"},{\"name\":\"billingPeriodOutOfSyncResourceEventsCounter\",\"type\":\"long\",\"default\":0},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"isFullBillingMonth\",\"type\":\"boolean\",\"default\":false},{\"name\":\"walletEntries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]}],\"messages\":{}}");
+  public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"AquariumUserState\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"types\":[{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[\"CronSpecTupleMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":\"EffectiveUnitPriceMsg\"}}]},{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[\"EffectivePriceTableMsg\",{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"PolicyMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"resourceMapping\",\"type\":{\"type\":\"map\",\"values\":\"ResourceTypeMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":\"FullPriceTableMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"DetailsMsg\",\"fields\":[{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementMsg\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"relatedIMEventOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"fullPriceTableRef\",\"type\":[\"FullPriceTableMsg\",\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[\"IMEventMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"ResourceInstanceChargingStateMsg\",\"fields\":[{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"previousEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"implicitlyIssuedStartEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"accumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldAccumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"previousValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"currentValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourcesChargingStateMsg\",\"fields\":[{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResourceInstance\",\"type\":{\"type\":\"map\",\"values\":\"ResourceInstanceChargingStateMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementHistoryMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"latestOccurredMillis\",\"type\":\"long\"},{\"name\":\"latestValidFromMillis\",\"type\":\"long\"},{\"name\":\"userCreationTimeMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"agreements\",\"type\":{\"type\":\"array\",\"items\":\"UserAgreementMsg\"}}]},{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]},{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":\"ChargeslotMsg\"}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":\"ResourceTypeMsg\"},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"isForRealtimeCalc\",\"type\":\"boolean\",\"default\":false}]},{\"type\":\"record\",\"name\":\"WalletEntriesMsg\",\"fields\":[{\"name\":\"entries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]},{\"type\":\"record\",\"name\":\"UserStateMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"parentOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentInStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"isFirst\",\"type\":\"boolean\",\"default\":false},{\"name\":\"isForFullMonth\",\"type\":\"boolean\",\"default\":false},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":\"ResourcesChargingStateMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"0\"},{\"name\":\"latestUpdateMillis\",\"type\":\"long\"},{\"name\":\"latestResourceEventOccurredMillis\",\"type\":\"long\"},{\"name\":\"billingPeriodOutOfSyncResourceEventsCounter\",\"type\":\"long\",\"default\":0},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"userAgreementHistory\",\"type\":\"UserAgreementHistoryMsg\"},{\"name\":\"walletEntries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]}],\"messages\":{}}");
 
   @SuppressWarnings("all")
   public interface Callback extends AquariumUserState {
index 00d2f5e..6263225 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
-  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"UserStateMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"parentOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentInStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"isFirst\",\"type\":\"boolean\",\"default\":false},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"ResourcesChargingStateMsg\",\"fields\":[{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResourceInstance\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"ResourceInstanceChargingStateMsg\",\"fields\":[{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"previousEvents\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]}}},{\"name\":\"implicitlyIssuedStartEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"accumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldAccumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"previousValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"currentValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"0\"},{\"name\":\"latestUpdateMillis\",\"type\":\"long\"},{\"name\":\"latestResourceEventOccurredMillis\",\"type\":\"long\"},{\"name\":\"billingPeriodOutOfSyncResourceEventsCounter\",\"type\":\"long\",\"default\":0},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"isFullBillingMonth\",\"type\":\"boolean\",\"default\":false},{\"name\":\"walletEntries\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false}]}}}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"UserStateMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"parentOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentInStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"isFirst\",\"type\":\"boolean\",\"default\":false},{\"name\":\"isForFullMonth\",\"type\":\"boolean\",\"default\":false},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"ResourcesChargingStateMsg\",\"fields\":[{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResourceInstance\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"ResourceInstanceChargingStateMsg\",\"fields\":[{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"previousEvents\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]}}},{\"name\":\"implicitlyIssuedStartEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"accumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldAccumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"previousValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"currentValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"0\"},{\"name\":\"latestUpdateMillis\",\"type\":\"long\"},{\"name\":\"latestResourceEventOccurredMillis\",\"type\":\"long\"},{\"name\":\"billingPeriodOutOfSyncResourceEventsCounter\",\"type\":\"long\",\"default\":0},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"userAgreementHistory\",\"type\":{\"type\":\"record\",\"name\":\"UserAgreementHistoryMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"latestOccurredMillis\",\"type\":\"long\"},{\"name\":\"latestValidFromMillis\",\"type\":\"long\"},{\"name\":\"userCreationTimeMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"agreements\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"UserAgreementMsg\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"relatedIMEventOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"fullPriceTableRef\",\"type\":[{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]},{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]}},{\"name\":\"walletEntries\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"isForRealtimeCalc\",\"type\":\"boolean\",\"default\":false}]}}}]}");
   @Deprecated public java.lang.String originalID;
   @Deprecated public java.lang.String inStoreID;
   @Deprecated public java.lang.String userID;
@@ -14,6 +14,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   @Deprecated public java.lang.String parentOriginalID;
   @Deprecated public java.lang.String parentInStoreID;
   @Deprecated public boolean isFirst;
+  @Deprecated public boolean isForFullMonth;
   @Deprecated public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> stateOfResources;
   @Deprecated public java.lang.String totalCredits;
   @Deprecated public long latestUpdateMillis;
@@ -22,7 +23,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   @Deprecated public int billingYear;
   @Deprecated public int billingMonth;
   @Deprecated public int billingMonthDay;
-  @Deprecated public boolean isFullBillingMonth;
+  @Deprecated public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg userAgreementHistory;
   @Deprecated public java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg> walletEntries;
 
   /**
@@ -33,7 +34,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   /**
    * All-args constructor.
    */
-  public UserStateMsg(java.lang.String originalID, java.lang.String inStoreID, java.lang.String userID, java.lang.Long occurredMillis, java.lang.String parentOriginalID, java.lang.String parentInStoreID, java.lang.Boolean isFirst, java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> stateOfResources, java.lang.String totalCredits, java.lang.Long latestUpdateMillis, java.lang.Long latestResourceEventOccurredMillis, java.lang.Long billingPeriodOutOfSyncResourceEventsCounter, java.lang.Integer billingYear, java.lang.Integer billingMonth, java.lang.Integer billingMonthDay, java.lang.Boolean isFullBillingMonth, java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg> walletEntries) {
+  public UserStateMsg(java.lang.String originalID, java.lang.String inStoreID, java.lang.String userID, java.lang.Long occurredMillis, java.lang.String parentOriginalID, java.lang.String parentInStoreID, java.lang.Boolean isFirst, java.lang.Boolean isForFullMonth, java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> stateOfResources, java.lang.String totalCredits, java.lang.Long latestUpdateMillis, java.lang.Long latestResourceEventOccurredMillis, java.lang.Long billingPeriodOutOfSyncResourceEventsCounter, java.lang.Integer billingYear, java.lang.Integer billingMonth, java.lang.Integer billingMonthDay, gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg userAgreementHistory, java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg> walletEntries) {
     this.originalID = originalID;
     this.inStoreID = inStoreID;
     this.userID = userID;
@@ -41,6 +42,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     this.parentOriginalID = parentOriginalID;
     this.parentInStoreID = parentInStoreID;
     this.isFirst = isFirst;
+    this.isForFullMonth = isForFullMonth;
     this.stateOfResources = stateOfResources;
     this.totalCredits = totalCredits;
     this.latestUpdateMillis = latestUpdateMillis;
@@ -49,7 +51,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     this.billingYear = billingYear;
     this.billingMonth = billingMonth;
     this.billingMonthDay = billingMonthDay;
-    this.isFullBillingMonth = isFullBillingMonth;
+    this.userAgreementHistory = userAgreementHistory;
     this.walletEntries = walletEntries;
   }
 
@@ -64,16 +66,17 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     case 4: return parentOriginalID;
     case 5: return parentInStoreID;
     case 6: return isFirst;
-    case 7: return stateOfResources;
-    case 8: return totalCredits;
-    case 9: return latestUpdateMillis;
-    case 10: return latestResourceEventOccurredMillis;
-    case 11: return billingPeriodOutOfSyncResourceEventsCounter;
-    case 12: return billingYear;
-    case 13: return billingMonth;
-    case 14: return billingMonthDay;
-    case 15: return isFullBillingMonth;
-    case 16: return walletEntries;
+    case 7: return isForFullMonth;
+    case 8: return stateOfResources;
+    case 9: return totalCredits;
+    case 10: return latestUpdateMillis;
+    case 11: return latestResourceEventOccurredMillis;
+    case 12: return billingPeriodOutOfSyncResourceEventsCounter;
+    case 13: return billingYear;
+    case 14: return billingMonth;
+    case 15: return billingMonthDay;
+    case 16: return userAgreementHistory;
+    case 17: return walletEntries;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -88,16 +91,17 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     case 4: parentOriginalID = (java.lang.String)value$; break;
     case 5: parentInStoreID = (java.lang.String)value$; break;
     case 6: isFirst = (java.lang.Boolean)value$; break;
-    case 7: stateOfResources = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>)value$; break;
-    case 8: totalCredits = (java.lang.String)value$; break;
-    case 9: latestUpdateMillis = (java.lang.Long)value$; break;
-    case 10: latestResourceEventOccurredMillis = (java.lang.Long)value$; break;
-    case 11: billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long)value$; break;
-    case 12: billingYear = (java.lang.Integer)value$; break;
-    case 13: billingMonth = (java.lang.Integer)value$; break;
-    case 14: billingMonthDay = (java.lang.Integer)value$; break;
-    case 15: isFullBillingMonth = (java.lang.Boolean)value$; break;
-    case 16: walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>)value$; break;
+    case 7: isForFullMonth = (java.lang.Boolean)value$; break;
+    case 8: stateOfResources = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>)value$; break;
+    case 9: totalCredits = (java.lang.String)value$; break;
+    case 10: latestUpdateMillis = (java.lang.Long)value$; break;
+    case 11: latestResourceEventOccurredMillis = (java.lang.Long)value$; break;
+    case 12: billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long)value$; break;
+    case 13: billingYear = (java.lang.Integer)value$; break;
+    case 14: billingMonth = (java.lang.Integer)value$; break;
+    case 15: billingMonthDay = (java.lang.Integer)value$; break;
+    case 16: userAgreementHistory = (gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg)value$; break;
+    case 17: walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>)value$; break;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -208,6 +212,21 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   }
 
   /**
+   * Gets the value of the 'isForFullMonth' field.
+   */
+  public java.lang.Boolean getIsForFullMonth() {
+    return isForFullMonth;
+  }
+
+  /**
+   * Sets the value of the 'isForFullMonth' field.
+   * @param value the value to set.
+   */
+  public void setIsForFullMonth(java.lang.Boolean value) {
+    this.isForFullMonth = value;
+  }
+
+  /**
    * Gets the value of the 'stateOfResources' field.
    */
   public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> getStateOfResources() {
@@ -328,18 +347,18 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   }
 
   /**
-   * Gets the value of the 'isFullBillingMonth' field.
+   * Gets the value of the 'userAgreementHistory' field.
    */
-  public java.lang.Boolean getIsFullBillingMonth() {
-    return isFullBillingMonth;
+  public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg getUserAgreementHistory() {
+    return userAgreementHistory;
   }
 
   /**
-   * Sets the value of the 'isFullBillingMonth' field.
+   * Sets the value of the 'userAgreementHistory' field.
    * @param value the value to set.
    */
-  public void setIsFullBillingMonth(java.lang.Boolean value) {
-    this.isFullBillingMonth = value;
+  public void setUserAgreementHistory(gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg value) {
+    this.userAgreementHistory = value;
   }
 
   /**
@@ -385,6 +404,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     private java.lang.String parentOriginalID;
     private java.lang.String parentInStoreID;
     private boolean isFirst;
+    private boolean isForFullMonth;
     private java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> stateOfResources;
     private java.lang.String totalCredits;
     private long latestUpdateMillis;
@@ -393,7 +413,7 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     private int billingYear;
     private int billingMonth;
     private int billingMonthDay;
-    private boolean isFullBillingMonth;
+    private gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg userAgreementHistory;
     private java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg> walletEntries;
 
     /** Creates a new Builder */
@@ -437,46 +457,50 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
         this.isFirst = (java.lang.Boolean) data().deepCopy(fields()[6].schema(), other.isFirst);
         fieldSetFlags()[6] = true;
       }
-      if (isValidValue(fields()[7], other.stateOfResources)) {
-        this.stateOfResources = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>) data().deepCopy(fields()[7].schema(), other.stateOfResources);
+      if (isValidValue(fields()[7], other.isForFullMonth)) {
+        this.isForFullMonth = (java.lang.Boolean) data().deepCopy(fields()[7].schema(), other.isForFullMonth);
         fieldSetFlags()[7] = true;
       }
-      if (isValidValue(fields()[8], other.totalCredits)) {
-        this.totalCredits = (java.lang.String) data().deepCopy(fields()[8].schema(), other.totalCredits);
+      if (isValidValue(fields()[8], other.stateOfResources)) {
+        this.stateOfResources = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>) data().deepCopy(fields()[8].schema(), other.stateOfResources);
         fieldSetFlags()[8] = true;
       }
-      if (isValidValue(fields()[9], other.latestUpdateMillis)) {
-        this.latestUpdateMillis = (java.lang.Long) data().deepCopy(fields()[9].schema(), other.latestUpdateMillis);
+      if (isValidValue(fields()[9], other.totalCredits)) {
+        this.totalCredits = (java.lang.String) data().deepCopy(fields()[9].schema(), other.totalCredits);
         fieldSetFlags()[9] = true;
       }
-      if (isValidValue(fields()[10], other.latestResourceEventOccurredMillis)) {
-        this.latestResourceEventOccurredMillis = (java.lang.Long) data().deepCopy(fields()[10].schema(), other.latestResourceEventOccurredMillis);
+      if (isValidValue(fields()[10], other.latestUpdateMillis)) {
+        this.latestUpdateMillis = (java.lang.Long) data().deepCopy(fields()[10].schema(), other.latestUpdateMillis);
         fieldSetFlags()[10] = true;
       }
-      if (isValidValue(fields()[11], other.billingPeriodOutOfSyncResourceEventsCounter)) {
-        this.billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long) data().deepCopy(fields()[11].schema(), other.billingPeriodOutOfSyncResourceEventsCounter);
+      if (isValidValue(fields()[11], other.latestResourceEventOccurredMillis)) {
+        this.latestResourceEventOccurredMillis = (java.lang.Long) data().deepCopy(fields()[11].schema(), other.latestResourceEventOccurredMillis);
         fieldSetFlags()[11] = true;
       }
-      if (isValidValue(fields()[12], other.billingYear)) {
-        this.billingYear = (java.lang.Integer) data().deepCopy(fields()[12].schema(), other.billingYear);
+      if (isValidValue(fields()[12], other.billingPeriodOutOfSyncResourceEventsCounter)) {
+        this.billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long) data().deepCopy(fields()[12].schema(), other.billingPeriodOutOfSyncResourceEventsCounter);
         fieldSetFlags()[12] = true;
       }
-      if (isValidValue(fields()[13], other.billingMonth)) {
-        this.billingMonth = (java.lang.Integer) data().deepCopy(fields()[13].schema(), other.billingMonth);
+      if (isValidValue(fields()[13], other.billingYear)) {
+        this.billingYear = (java.lang.Integer) data().deepCopy(fields()[13].schema(), other.billingYear);
         fieldSetFlags()[13] = true;
       }
-      if (isValidValue(fields()[14], other.billingMonthDay)) {
-        this.billingMonthDay = (java.lang.Integer) data().deepCopy(fields()[14].schema(), other.billingMonthDay);
+      if (isValidValue(fields()[14], other.billingMonth)) {
+        this.billingMonth = (java.lang.Integer) data().deepCopy(fields()[14].schema(), other.billingMonth);
         fieldSetFlags()[14] = true;
       }
-      if (isValidValue(fields()[15], other.isFullBillingMonth)) {
-        this.isFullBillingMonth = (java.lang.Boolean) data().deepCopy(fields()[15].schema(), other.isFullBillingMonth);
+      if (isValidValue(fields()[15], other.billingMonthDay)) {
+        this.billingMonthDay = (java.lang.Integer) data().deepCopy(fields()[15].schema(), other.billingMonthDay);
         fieldSetFlags()[15] = true;
       }
-      if (isValidValue(fields()[16], other.walletEntries)) {
-        this.walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) data().deepCopy(fields()[16].schema(), other.walletEntries);
+      if (isValidValue(fields()[16], other.userAgreementHistory)) {
+        this.userAgreementHistory = (gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg) data().deepCopy(fields()[16].schema(), other.userAgreementHistory);
         fieldSetFlags()[16] = true;
       }
+      if (isValidValue(fields()[17], other.walletEntries)) {
+        this.walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) data().deepCopy(fields()[17].schema(), other.walletEntries);
+        fieldSetFlags()[17] = true;
+      }
     }
 
     /** Gets the value of the 'originalID' field */
@@ -652,6 +676,30 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
       return this;
     }
 
+    /** Gets the value of the 'isForFullMonth' field */
+    public java.lang.Boolean getIsForFullMonth() {
+      return isForFullMonth;
+    }
+    
+    /** Sets the value of the 'isForFullMonth' field */
+    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setIsForFullMonth(boolean value) {
+      validate(fields()[7], value);
+      this.isForFullMonth = value;
+      fieldSetFlags()[7] = true;
+      return this; 
+    }
+    
+    /** Checks whether the 'isForFullMonth' field has been set */
+    public boolean hasIsForFullMonth() {
+      return fieldSetFlags()[7];
+    }
+    
+    /** Clears the value of the 'isForFullMonth' field */
+    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearIsForFullMonth() {
+      fieldSetFlags()[7] = false;
+      return this;
+    }
+
     /** Gets the value of the 'stateOfResources' field */
     public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> getStateOfResources() {
       return stateOfResources;
@@ -659,21 +707,21 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'stateOfResources' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setStateOfResources(java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> value) {
-      validate(fields()[7], value);
+      validate(fields()[8], value);
       this.stateOfResources = value;
-      fieldSetFlags()[7] = true;
+      fieldSetFlags()[8] = true;
       return this; 
     }
     
     /** Checks whether the 'stateOfResources' field has been set */
     public boolean hasStateOfResources() {
-      return fieldSetFlags()[7];
+      return fieldSetFlags()[8];
     }
     
     /** Clears the value of the 'stateOfResources' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearStateOfResources() {
       stateOfResources = null;
-      fieldSetFlags()[7] = false;
+      fieldSetFlags()[8] = false;
       return this;
     }
 
@@ -684,21 +732,21 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'totalCredits' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setTotalCredits(java.lang.String value) {
-      validate(fields()[8], value);
+      validate(fields()[9], value);
       this.totalCredits = value;
-      fieldSetFlags()[8] = true;
+      fieldSetFlags()[9] = true;
       return this; 
     }
     
     /** Checks whether the 'totalCredits' field has been set */
     public boolean hasTotalCredits() {
-      return fieldSetFlags()[8];
+      return fieldSetFlags()[9];
     }
     
     /** Clears the value of the 'totalCredits' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearTotalCredits() {
       totalCredits = null;
-      fieldSetFlags()[8] = false;
+      fieldSetFlags()[9] = false;
       return this;
     }
 
@@ -709,20 +757,20 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'latestUpdateMillis' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setLatestUpdateMillis(long value) {
-      validate(fields()[9], value);
+      validate(fields()[10], value);
       this.latestUpdateMillis = value;
-      fieldSetFlags()[9] = true;
+      fieldSetFlags()[10] = true;
       return this; 
     }
     
     /** Checks whether the 'latestUpdateMillis' field has been set */
     public boolean hasLatestUpdateMillis() {
-      return fieldSetFlags()[9];
+      return fieldSetFlags()[10];
     }
     
     /** Clears the value of the 'latestUpdateMillis' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearLatestUpdateMillis() {
-      fieldSetFlags()[9] = false;
+      fieldSetFlags()[10] = false;
       return this;
     }
 
@@ -733,20 +781,20 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'latestResourceEventOccurredMillis' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setLatestResourceEventOccurredMillis(long value) {
-      validate(fields()[10], value);
+      validate(fields()[11], value);
       this.latestResourceEventOccurredMillis = value;
-      fieldSetFlags()[10] = true;
+      fieldSetFlags()[11] = true;
       return this; 
     }
     
     /** Checks whether the 'latestResourceEventOccurredMillis' field has been set */
     public boolean hasLatestResourceEventOccurredMillis() {
-      return fieldSetFlags()[10];
+      return fieldSetFlags()[11];
     }
     
     /** Clears the value of the 'latestResourceEventOccurredMillis' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearLatestResourceEventOccurredMillis() {
-      fieldSetFlags()[10] = false;
+      fieldSetFlags()[11] = false;
       return this;
     }
 
@@ -757,20 +805,20 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'billingPeriodOutOfSyncResourceEventsCounter' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setBillingPeriodOutOfSyncResourceEventsCounter(long value) {
-      validate(fields()[11], value);
+      validate(fields()[12], value);
       this.billingPeriodOutOfSyncResourceEventsCounter = value;
-      fieldSetFlags()[11] = true;
+      fieldSetFlags()[12] = true;
       return this; 
     }
     
     /** Checks whether the 'billingPeriodOutOfSyncResourceEventsCounter' field has been set */
     public boolean hasBillingPeriodOutOfSyncResourceEventsCounter() {
-      return fieldSetFlags()[11];
+      return fieldSetFlags()[12];
     }
     
     /** Clears the value of the 'billingPeriodOutOfSyncResourceEventsCounter' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingPeriodOutOfSyncResourceEventsCounter() {
-      fieldSetFlags()[11] = false;
+      fieldSetFlags()[12] = false;
       return this;
     }
 
@@ -781,20 +829,20 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'billingYear' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setBillingYear(int value) {
-      validate(fields()[12], value);
+      validate(fields()[13], value);
       this.billingYear = value;
-      fieldSetFlags()[12] = true;
+      fieldSetFlags()[13] = true;
       return this; 
     }
     
     /** Checks whether the 'billingYear' field has been set */
     public boolean hasBillingYear() {
-      return fieldSetFlags()[12];
+      return fieldSetFlags()[13];
     }
     
     /** Clears the value of the 'billingYear' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingYear() {
-      fieldSetFlags()[12] = false;
+      fieldSetFlags()[13] = false;
       return this;
     }
 
@@ -805,20 +853,20 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'billingMonth' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setBillingMonth(int value) {
-      validate(fields()[13], value);
+      validate(fields()[14], value);
       this.billingMonth = value;
-      fieldSetFlags()[13] = true;
+      fieldSetFlags()[14] = true;
       return this; 
     }
     
     /** Checks whether the 'billingMonth' field has been set */
     public boolean hasBillingMonth() {
-      return fieldSetFlags()[13];
+      return fieldSetFlags()[14];
     }
     
     /** Clears the value of the 'billingMonth' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingMonth() {
-      fieldSetFlags()[13] = false;
+      fieldSetFlags()[14] = false;
       return this;
     }
 
@@ -829,44 +877,45 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'billingMonthDay' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setBillingMonthDay(int value) {
-      validate(fields()[14], value);
+      validate(fields()[15], value);
       this.billingMonthDay = value;
-      fieldSetFlags()[14] = true;
+      fieldSetFlags()[15] = true;
       return this; 
     }
     
     /** Checks whether the 'billingMonthDay' field has been set */
     public boolean hasBillingMonthDay() {
-      return fieldSetFlags()[14];
+      return fieldSetFlags()[15];
     }
     
     /** Clears the value of the 'billingMonthDay' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingMonthDay() {
-      fieldSetFlags()[14] = false;
+      fieldSetFlags()[15] = false;
       return this;
     }
 
-    /** Gets the value of the 'isFullBillingMonth' field */
-    public java.lang.Boolean getIsFullBillingMonth() {
-      return isFullBillingMonth;
+    /** Gets the value of the 'userAgreementHistory' field */
+    public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg getUserAgreementHistory() {
+      return userAgreementHistory;
     }
     
-    /** Sets the value of the 'isFullBillingMonth' field */
-    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setIsFullBillingMonth(boolean value) {
-      validate(fields()[15], value);
-      this.isFullBillingMonth = value;
-      fieldSetFlags()[15] = true;
+    /** Sets the value of the 'userAgreementHistory' field */
+    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setUserAgreementHistory(gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg value) {
+      validate(fields()[16], value);
+      this.userAgreementHistory = value;
+      fieldSetFlags()[16] = true;
       return this; 
     }
     
-    /** Checks whether the 'isFullBillingMonth' field has been set */
-    public boolean hasIsFullBillingMonth() {
-      return fieldSetFlags()[15];
+    /** Checks whether the 'userAgreementHistory' field has been set */
+    public boolean hasUserAgreementHistory() {
+      return fieldSetFlags()[16];
     }
     
-    /** Clears the value of the 'isFullBillingMonth' field */
-    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearIsFullBillingMonth() {
-      fieldSetFlags()[15] = false;
+    /** Clears the value of the 'userAgreementHistory' field */
+    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearUserAgreementHistory() {
+      userAgreementHistory = null;
+      fieldSetFlags()[16] = false;
       return this;
     }
 
@@ -877,21 +926,21 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'walletEntries' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setWalletEntries(java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg> value) {
-      validate(fields()[16], value);
+      validate(fields()[17], value);
       this.walletEntries = value;
-      fieldSetFlags()[16] = true;
+      fieldSetFlags()[17] = true;
       return this; 
     }
     
     /** Checks whether the 'walletEntries' field has been set */
     public boolean hasWalletEntries() {
-      return fieldSetFlags()[16];
+      return fieldSetFlags()[17];
     }
     
     /** Clears the value of the 'walletEntries' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearWalletEntries() {
       walletEntries = null;
-      fieldSetFlags()[16] = false;
+      fieldSetFlags()[17] = false;
       return this;
     }
 
@@ -906,16 +955,17 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
         record.parentOriginalID = fieldSetFlags()[4] ? this.parentOriginalID : (java.lang.String) defaultValue(fields()[4]);
         record.parentInStoreID = fieldSetFlags()[5] ? this.parentInStoreID : (java.lang.String) defaultValue(fields()[5]);
         record.isFirst = fieldSetFlags()[6] ? this.isFirst : (java.lang.Boolean) defaultValue(fields()[6]);
-        record.stateOfResources = fieldSetFlags()[7] ? this.stateOfResources : (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>) defaultValue(fields()[7]);
-        record.totalCredits = fieldSetFlags()[8] ? this.totalCredits : (java.lang.String) defaultValue(fields()[8]);
-        record.latestUpdateMillis = fieldSetFlags()[9] ? this.latestUpdateMillis : (java.lang.Long) defaultValue(fields()[9]);
-        record.latestResourceEventOccurredMillis = fieldSetFlags()[10] ? this.latestResourceEventOccurredMillis : (java.lang.Long) defaultValue(fields()[10]);
-        record.billingPeriodOutOfSyncResourceEventsCounter = fieldSetFlags()[11] ? this.billingPeriodOutOfSyncResourceEventsCounter : (java.lang.Long) defaultValue(fields()[11]);
-        record.billingYear = fieldSetFlags()[12] ? this.billingYear : (java.lang.Integer) defaultValue(fields()[12]);
-        record.billingMonth = fieldSetFlags()[13] ? this.billingMonth : (java.lang.Integer) defaultValue(fields()[13]);
-        record.billingMonthDay = fieldSetFlags()[14] ? this.billingMonthDay : (java.lang.Integer) defaultValue(fields()[14]);
-        record.isFullBillingMonth = fieldSetFlags()[15] ? this.isFullBillingMonth : (java.lang.Boolean) defaultValue(fields()[15]);
-        record.walletEntries = fieldSetFlags()[16] ? this.walletEntries : (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) defaultValue(fields()[16]);
+        record.isForFullMonth = fieldSetFlags()[7] ? this.isForFullMonth : (java.lang.Boolean) defaultValue(fields()[7]);
+        record.stateOfResources = fieldSetFlags()[8] ? this.stateOfResources : (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>) defaultValue(fields()[8]);
+        record.totalCredits = fieldSetFlags()[9] ? this.totalCredits : (java.lang.String) defaultValue(fields()[9]);
+        record.latestUpdateMillis = fieldSetFlags()[10] ? this.latestUpdateMillis : (java.lang.Long) defaultValue(fields()[10]);
+        record.latestResourceEventOccurredMillis = fieldSetFlags()[11] ? this.latestResourceEventOccurredMillis : (java.lang.Long) defaultValue(fields()[11]);
+        record.billingPeriodOutOfSyncResourceEventsCounter = fieldSetFlags()[12] ? this.billingPeriodOutOfSyncResourceEventsCounter : (java.lang.Long) defaultValue(fields()[12]);
+        record.billingYear = fieldSetFlags()[13] ? this.billingYear : (java.lang.Integer) defaultValue(fields()[13]);
+        record.billingMonth = fieldSetFlags()[14] ? this.billingMonth : (java.lang.Integer) defaultValue(fields()[14]);
+        record.billingMonthDay = fieldSetFlags()[15] ? this.billingMonthDay : (java.lang.Integer) defaultValue(fields()[15]);
+        record.userAgreementHistory = fieldSetFlags()[16] ? this.userAgreementHistory : (gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg) defaultValue(fields()[16]);
+        record.walletEntries = fieldSetFlags()[17] ? this.walletEntries : (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) defaultValue(fields()[17]);
         return record;
       } catch (Exception e) {
         throw new org.apache.avro.AvroRuntimeException(e);
index 9e4752e..b692758 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class WalletEntriesMsg extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
-  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"WalletEntriesMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"entries\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"}}]}}},{\"name\":\"resourceType\",\"type\":{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false}]}}}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"WalletEntriesMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"entries\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"}}]}}},{\"name\":\"resourceType\",\"type\":{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"isForRealtimeCalc\",\"type\":\"boolean\",\"default\":false}]}}}]}");
   @Deprecated public java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg> entries;
 
   /**
index 815be3c..0fcade5 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
-  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"}}]}}},{\"name\":\"resourceType\",\"type\":{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"}}]}}},{\"name\":\"resourceType\",\"type\":{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"isForRealtimeCalc\",\"type\":\"boolean\",\"default\":false}]}");
   @Deprecated public java.lang.String userID;
   @Deprecated public java.lang.String sumOfCreditsToSubtract;
   @Deprecated public java.lang.String oldTotalCredits;
@@ -21,6 +21,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
   @Deprecated public java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceEventMsg> resourceEvents;
   @Deprecated public gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg resourceType;
   @Deprecated public boolean isSynthetic;
+  @Deprecated public boolean isForRealtimeCalc;
 
   /**
    * Default constructor.
@@ -30,7 +31,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
   /**
    * All-args constructor.
    */
-  public WalletEntryMsg(java.lang.String userID, java.lang.String sumOfCreditsToSubtract, java.lang.String oldTotalCredits, java.lang.String newTotalCredits, java.lang.Long whenComputedMillis, java.lang.Long referenceStartMillis, java.lang.Long referenceStopMillis, java.lang.Integer billingYear, java.lang.Integer billingMonth, java.lang.Integer billingMonthDay, java.util.List<gr.grnet.aquarium.message.avro.gen.ChargeslotMsg> chargeslots, java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceEventMsg> resourceEvents, gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg resourceType, java.lang.Boolean isSynthetic) {
+  public WalletEntryMsg(java.lang.String userID, java.lang.String sumOfCreditsToSubtract, java.lang.String oldTotalCredits, java.lang.String newTotalCredits, java.lang.Long whenComputedMillis, java.lang.Long referenceStartMillis, java.lang.Long referenceStopMillis, java.lang.Integer billingYear, java.lang.Integer billingMonth, java.lang.Integer billingMonthDay, java.util.List<gr.grnet.aquarium.message.avro.gen.ChargeslotMsg> chargeslots, java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceEventMsg> resourceEvents, gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg resourceType, java.lang.Boolean isSynthetic, java.lang.Boolean isForRealtimeCalc) {
     this.userID = userID;
     this.sumOfCreditsToSubtract = sumOfCreditsToSubtract;
     this.oldTotalCredits = oldTotalCredits;
@@ -45,6 +46,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
     this.resourceEvents = resourceEvents;
     this.resourceType = resourceType;
     this.isSynthetic = isSynthetic;
+    this.isForRealtimeCalc = isForRealtimeCalc;
   }
 
   public org.apache.avro.Schema getSchema() { return SCHEMA$; }
@@ -65,6 +67,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
     case 11: return resourceEvents;
     case 12: return resourceType;
     case 13: return isSynthetic;
+    case 14: return isForRealtimeCalc;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -86,6 +89,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
     case 11: resourceEvents = (java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceEventMsg>)value$; break;
     case 12: resourceType = (gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg)value$; break;
     case 13: isSynthetic = (java.lang.Boolean)value$; break;
+    case 14: isForRealtimeCalc = (java.lang.Boolean)value$; break;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -300,6 +304,21 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
     this.isSynthetic = value;
   }
 
+  /**
+   * Gets the value of the 'isForRealtimeCalc' field.
+   */
+  public java.lang.Boolean getIsForRealtimeCalc() {
+    return isForRealtimeCalc;
+  }
+
+  /**
+   * Sets the value of the 'isForRealtimeCalc' field.
+   * @param value the value to set.
+   */
+  public void setIsForRealtimeCalc(java.lang.Boolean value) {
+    this.isForRealtimeCalc = value;
+  }
+
   /** Creates a new WalletEntryMsg RecordBuilder */
   public static gr.grnet.aquarium.message.avro.gen.WalletEntryMsg.Builder newBuilder() {
     return new gr.grnet.aquarium.message.avro.gen.WalletEntryMsg.Builder();
@@ -335,6 +354,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
     private java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceEventMsg> resourceEvents;
     private gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg resourceType;
     private boolean isSynthetic;
+    private boolean isForRealtimeCalc;
 
     /** Creates a new Builder */
     private Builder() {
@@ -405,6 +425,10 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
         this.isSynthetic = (java.lang.Boolean) data().deepCopy(fields()[13].schema(), other.isSynthetic);
         fieldSetFlags()[13] = true;
       }
+      if (isValidValue(fields()[14], other.isForRealtimeCalc)) {
+        this.isForRealtimeCalc = (java.lang.Boolean) data().deepCopy(fields()[14].schema(), other.isForRealtimeCalc);
+        fieldSetFlags()[14] = true;
+      }
     }
 
     /** Gets the value of the 'userID' field */
@@ -750,6 +774,30 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
       return this;
     }
 
+    /** Gets the value of the 'isForRealtimeCalc' field */
+    public java.lang.Boolean getIsForRealtimeCalc() {
+      return isForRealtimeCalc;
+    }
+    
+    /** Sets the value of the 'isForRealtimeCalc' field */
+    public gr.grnet.aquarium.message.avro.gen.WalletEntryMsg.Builder setIsForRealtimeCalc(boolean value) {
+      validate(fields()[14], value);
+      this.isForRealtimeCalc = value;
+      fieldSetFlags()[14] = true;
+      return this; 
+    }
+    
+    /** Checks whether the 'isForRealtimeCalc' field has been set */
+    public boolean hasIsForRealtimeCalc() {
+      return fieldSetFlags()[14];
+    }
+    
+    /** Clears the value of the 'isForRealtimeCalc' field */
+    public gr.grnet.aquarium.message.avro.gen.WalletEntryMsg.Builder clearIsForRealtimeCalc() {
+      fieldSetFlags()[14] = false;
+      return this;
+    }
+
     @Override
     public WalletEntryMsg build() {
       try {
@@ -768,6 +816,7 @@ public class WalletEntryMsg extends org.apache.avro.specific.SpecificRecordBase
         record.resourceEvents = fieldSetFlags()[11] ? this.resourceEvents : (java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceEventMsg>) defaultValue(fields()[11]);
         record.resourceType = fieldSetFlags()[12] ? this.resourceType : (gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg) defaultValue(fields()[12]);
         record.isSynthetic = fieldSetFlags()[13] ? this.isSynthetic : (java.lang.Boolean) defaultValue(fields()[13]);
+        record.isForRealtimeCalc = fieldSetFlags()[14] ? this.isForRealtimeCalc : (java.lang.Boolean) defaultValue(fields()[14]);
         return record;
       } catch (Exception e) {
         throw new org.apache.avro.AvroRuntimeException(e);
index 3f735d5..c372511 100644 (file)
@@ -54,7 +54,6 @@ import gr.grnet.aquarium.util.{Loggable, Lifecycle}
 import java.io.File
 import java.util.concurrent.atomic.AtomicBoolean
 import org.slf4j.{LoggerFactory, Logger}
-import gr.grnet.aquarium.charging.state.UserStateBootstrap
 import java.util.{Map ⇒ JMap}
 import java.util.{HashMap ⇒ JHashMap}
 
@@ -428,13 +427,6 @@ final class Aquarium(env: Env) extends Lifecycle with Loggable {
     Real.Zero
   }
 
-  def getUserStateBootstrap(imEvent: IMEventMsg): UserStateBootstrap = {
-    UserStateBootstrap(
-      this.initialUserAgreement(imEvent),
-      this.initialUserBalance(imEvent.getRole, imEvent.getOccurredMillis)
-    )
-  }
-
   def chargingBehaviorOf(resourceType: ResourceTypeMsg): ChargingBehavior = {
     // A resource type never changes charging behavior. By definition.
     val className = resourceType.getChargingBehaviorClass
index 3fde4f6..5840379 100644 (file)
@@ -50,9 +50,9 @@ import gr.grnet.aquarium.actor.message.GetUserWalletRequest
 import gr.grnet.aquarium.actor.message.GetUserWalletResponse
 import gr.grnet.aquarium.actor.message.GetUserWalletResponseData
 import gr.grnet.aquarium.actor.message.config.AquariumPropertiesLoaded
-import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel, UserStateBootstrap}
-import gr.grnet.aquarium.message.avro.gen.{ResourceTypeMsg, UserAgreementHistoryMsg, IMEventMsg, ResourceEventMsg, UserStateMsg}
-import gr.grnet.aquarium.message.avro.{ModelFactory, MessageFactory, MessageHelpers, AvroHelpers}
+import gr.grnet.aquarium.charging.state.UserStateModel
+import gr.grnet.aquarium.message.avro.gen.{UserAgreementHistoryMsg, IMEventMsg, ResourceEventMsg}
+import gr.grnet.aquarium.message.avro.{ModelFactory, MessageFactory, MessageHelpers}
 import gr.grnet.aquarium.service.event.BalanceEvent
 import gr.grnet.aquarium.util.date.TimeHelpers
 import gr.grnet.aquarium.util.{LogHelpers, shortClassNameOf}
@@ -66,15 +66,14 @@ import gr.grnet.aquarium.charging.bill.BillEntryMsg
 
 class UserActor extends ReflectiveRoleableActor {
   private[this] var _imMsgCount = 0
-  private[this] var _userStateMsg: UserStateMsg = _
-  private[this] var _userAgreementHistoryModel: UserAgreementHistoryModel = _
+  private[this] var _userStateModel: UserStateModel = _
 
   def userID = {
     if(!haveUserState) {
       throw new AquariumInternalError("%s not initialized")
     }
 
-    this._userStateMsg.getUserID
+    this._userStateModel.userID
   }
 
   override def postStop() {
@@ -102,22 +101,32 @@ class UserActor extends ReflectiveRoleableActor {
   def onAquariumPropertiesLoaded(event: AquariumPropertiesLoaded): Unit = {
   }
 
-  private[this] def unsafeUserCreationIMEventMsg = this._userAgreementHistoryModel.unsafeUserCreationIMEvent
-  private[this] def haveAgreements = this._userAgreementHistoryModel ne null
-  private[this] def isUserCreated = haveAgreements && this._userAgreementHistoryModel.hasUserCreationEvent
-  private[this] def haveUserState = this._userStateMsg ne null
+  private[this] def unsafeUserCreationIMEventMsg = {
+    this._userStateModel.unsafeUserCreationIMEvent
+  }
+
+  private[this] def haveAgreements = {
+    (this._userStateModel ne null)
+  }
+
+  private[this] def haveUserCreationEvent = {
+    haveAgreements &&
+    this._userStateModel.hasUserCreationEvent
+  }
+
+  private[this] def haveUserState = {
+    (this._userStateModel ne null)
+  }
 
   /**
    * Creates the agreement history from all the stored IMEvents.
    *
    * @return (`true` iff there was a user CREATE event, the number of events processed)
    */
-  private[this] def createUserAgreementHistoryFromStoredIMEvents(): (Boolean, Int) = {
+  private[this] def createUserAgreementHistoryFromIMEvents(userID: String): (Boolean, Int) = {
     DEBUG("createUserAgreementHistoryFromStoredIMEvents()")
     assert(haveUserState, "haveUserState")
 
-    val historyMsg = MessageFactory.newUserAgreementHistoryMsg(userID)
-    this._userAgreementHistoryModel = ModelFactory.newUserAgreementHistoryModel(historyMsg)
 
     var _imcounter = 0
 
@@ -140,31 +149,51 @@ class UserActor extends ReflectiveRoleableActor {
           "aquarium.unsafeFullPriceTableForRoleAt(%s, %s) ne null".format(role, effectiveFromMillis)
         )
 
-        this._userAgreementHistoryModel.insertUserAgreementMsgFromIMEvent(imEvent)
+        this._userStateModel.insertUserAgreementMsgFromIMEvent(imEvent)
         true
       }
     }
 
-    DEBUG("Agreements: %s", this._userAgreementHistoryModel)
+    this._imMsgCount = _imcounter
+
+    DEBUG("Agreements: %s", this._userStateModel.userAgreementHistoryMsg)
     (hadCreateEvent, _imcounter)
   }
 
+  private[this] def saveFirstUserState(userID: String) {
+    this._userStateModel.userStateMsg.setIsFirst(true)
+    this._userStateModel.updateUserStateMsg(
+      aquarium.userStateStore.insertUserState(this._userStateModel.userStateMsg)
+    )
+  }
+
+  private[this] def saveSubsequentUserState() {
+    this._userStateModel.userStateMsg.setIsFirst(false)
+    this._userStateModel.updateUserStateMsg(
+      aquarium.userStateStore.insertUserState(this._userStateModel.userStateMsg)
+    )
+  }
+
+  private[this] def loadLastKnownUserStateAndUpdateAgreements(historyMsg: UserAgreementHistoryMsg) {
+    val userID = historyMsg.getUserID
+    val latestUserStateOpt = aquarium.userStateStore.findLatestUserState(userID)
+    latestUserStateOpt match {
+      case None ⇒
+        // First user state ever
+        saveFirstUserState(userID)
+
+      case Some(latestUserState) ⇒
+        this._userStateModel.updateUserStateMsg(latestUserState)
+        this._userStateModel.updateUserAgreementHistoryMsg(historyMsg)
+    }
+  }
   /**
    * Processes [[gr.grnet.aquarium.message.avro.gen.IMEventMsg]]s that come directly from the
    * messaging hub (rabbitmq).
    */
   def onIMEventMsg(imEvent: IMEventMsg) {
-    if(!isUserCreated && MessageHelpers.isIMEventCreate(imEvent)) {
-      assert(this._imMsgCount == 0, "this._imMsgCount == 0")
-      // Create the full agreement history from the original sources (IMEvents)
-      val (userCreated, imEventsCount) = createUserAgreementHistoryFromStoredIMEvents()
-
-      this._imMsgCount = imEventsCount
-      return
-    }
-
     // Check for out of sync (regarding IMEvents)
-    val isOutOfSyncIM = imEvent.getOccurredMillis < this._userAgreementHistoryModel.latestIMEventOccurredMillis
+    val isOutOfSyncIM = imEvent.getOccurredMillis < this._userStateModel.latestIMEventOccurredMillis
     if(isOutOfSyncIM) {
       // clear all resource state
       // FIXME implement
@@ -180,17 +209,19 @@ class UserActor extends ReflectiveRoleableActor {
       return
     }
 
-    // OK, seems good
-    assert(!MessageHelpers.isIMEventCreate(imEvent), "!MessageHelpers.isIMEventCreate(imEvent)")
-
     // Make new agreement
-    this._userAgreementHistoryModel.insertUserAgreementMsgFromIMEvent(imEvent)
+    this._userStateModel.insertUserAgreementMsgFromIMEvent(imEvent)
     this._imMsgCount += 1
-    DEBUG("Agreements: %s", this._userAgreementHistoryModel)
+
+    if(haveUserCreationEvent) {
+      loadLastKnownUserStateAndUpdateAgreements(this._userStateModel.userAgreementHistoryMsg)
+    }
+
+    DEBUG("Agreements: %s", this._userStateModel.userAgreementHistoryMsg)
   }
 
   def onResourceEventMsg(rcEvent: ResourceEventMsg) {
-    if(!isUserCreated) {
+    if(!haveUserCreationEvent) {
       DEBUG("No agreements. Ignoring %s", rcEvent)
 
       return
@@ -198,24 +229,23 @@ class UserActor extends ReflectiveRoleableActor {
 
     assert(haveUserState, "haveUserState")
 
-    val oldTotalCredits = Real(this._userStateMsg.getTotalCredits)
+    val oldTotalCredits = this._userStateModel.totalCreditsAsReal
 
     chargingService.processResourceEvent(
       rcEvent.getReceivedMillis,
       rcEvent,
-      this._userAgreementHistoryModel,
-      this._userStateMsg,
+      this._userStateModel,
       aquarium.currentResourceMapping,
       true
     )
 
-    val newTotalCredits = Real(this._userStateMsg.getTotalCredits)
+    val newTotalCredits = this._userStateModel.totalCreditsAsReal
 
     if(oldTotalCredits.signum * newTotalCredits.signum < 0) {
       aquarium.eventBus ! new BalanceEvent(userID, newTotalCredits >= 0)
     }
 
-    DEBUG("Updated %s", this._userStateMsg)
+    DEBUG("Updated %s", this._userStateModel)
   }
 
   def onGetUserBillRequest(event: GetUserBillRequest): Unit = {
@@ -228,7 +258,7 @@ class UserActor extends ReflectiveRoleableActor {
           case None => Map[String,ResourceType]()
           case Some(policy:PolicyModel) => policy.resourceTypesMap
       }
-      val state= if(haveUserState) Some(this._userStateMsg) else None
+      val state= if(haveUserState) Some(this._userStateModel.userStateMsg) else None
       val billEntryMsg = BillEntryMsg.fromWorkingUserState(timeslot,this.userID,state,resourceTypes)
       //val billEntryMsg = MessageFactory.createBillEntryMsg(billEntry)
       //logger.debug("BILL ENTRY MSG: " + billEntryMsg.toString)
@@ -249,13 +279,12 @@ class UserActor extends ReflectiveRoleableActor {
         // (User CREATEd, with balance state)
         val realtimeMillis = TimeHelpers.nowMillis()
         chargingService.calculateRealtimeUserState(
-          this._userAgreementHistoryModel,
-          this._userStateMsg,
+          this._userStateModel,
           aquarium.currentResourceMapping,
           realtimeMillis
         )
 
-        sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this.userID, this._userStateMsg.getTotalCredits)))
+        sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this.userID, this._userStateModel.totalCredits)))
 
       case (true, false) ⇒
         // (User CREATEd, no balance state)
@@ -284,13 +313,12 @@ class UserActor extends ReflectiveRoleableActor {
       case true ⇒
         val realtimeMillis = TimeHelpers.nowMillis()
         chargingService.calculateRealtimeUserState(
-          this._userAgreementHistoryModel,
-          this._userStateMsg,
+          this._userStateModel,
           aquarium.currentResourceMapping,
           realtimeMillis
         )
 
-        sender ! GetUserStateResponse(Right(this._userStateMsg))
+        sender ! GetUserStateResponse(Right(this._userStateModel.userStateMsg))
 
       case false ⇒
         sender ! GetUserStateResponse(Left("No state for user %s [AQU-STA-0006]".format(event.userID)), 404)
@@ -303,8 +331,7 @@ class UserActor extends ReflectiveRoleableActor {
         DEBUG("haveWorkingUserState: %s", event)
         val realtimeMillis = TimeHelpers.nowMillis()
         chargingService.calculateRealtimeUserState(
-          this._userAgreementHistoryModel,
-          this._userStateMsg,
+          this._userStateModel,
           aquarium.currentResourceMapping,
           realtimeMillis
         )
@@ -313,8 +340,8 @@ class UserActor extends ReflectiveRoleableActor {
           Right(
             GetUserWalletResponseData(
               this.userID,
-              this._userStateMsg.getTotalCredits,
-              MessageFactory.newWalletEntriesMsg(this._userStateMsg.getWalletEntries)
+              this._userStateModel.totalCredits,
+              MessageFactory.newWalletEntriesMsg(this._userStateModel.userStateMsg.getWalletEntries)
             )))
 
       case false ⇒
@@ -337,12 +364,23 @@ class UserActor extends ReflectiveRoleableActor {
     }
   }
 
+  /**
+   * Initializes the actor's internal state.
+   *
+   * @param userID
+   */
   def onSetUserActorUserID(userID: String) {
-    this._userStateMsg = MessageFactory.newInitialUserStateMsg(
+    // Create the full agreement history from the original sources (IMEvents)
+    this._userStateModel = ModelFactory.newInitialUserStateModel(
       userID,
-      Real.Zero,
+      Real(0),
       TimeHelpers.nowMillis()
     )
+
+    val (userCreated, imEventsCount) = createUserAgreementHistoryFromIMEvents(userID)
+    if(userCreated) {
+      loadLastKnownUserStateAndUpdateAgreements(this._userStateModel.userAgreementHistoryMsg)
+    }
   }
 
   private[this] def D_userID = {
index 96c27bd..1173997 100644 (file)
@@ -37,7 +37,7 @@ package gr.grnet.aquarium.charging
 
 import gr.grnet.aquarium.Aquarium
 import gr.grnet.aquarium.Real
-import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
+import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel}
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
@@ -89,8 +89,7 @@ trait ChargingBehavior {
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
       resourcesChargingState: ResourcesChargingStateMsg,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
-      userStateMsg: UserStateMsg,
+      userStateModel: UserStateModel,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
   ): (Int, Real)
 
index 1c3b02e..6b93fbd 100644 (file)
@@ -45,7 +45,7 @@ import gr.grnet.aquarium.util.date.{MutableDateCalc, TimeHelpers}
 import gr.grnet.aquarium.util.{Lifecycle, Loggable}
 import gr.grnet.aquarium.{Real, AquariumInternalError, AquariumAwareSkeleton}
 import java.util.{Map ⇒ JMap}
-import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
+import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel}
 
 /**
  *
@@ -64,12 +64,14 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   //- Lifecycle
 
   def calculateRealtimeUserState(
-      userAgreementHistoryModel: UserAgreementHistoryModel,
-      userStateMsg: UserStateMsg,
+      userStateModel: UserStateModel,
       resourceMapping: JMap[String, ResourceTypeMsg],
       realtimeMillis: Long
   ) {
 
+    val userStateMsg = userStateModel.userStateMsg
+    val userAgreementHistoryModel = userStateModel.userAgreementHistoryMsg
+
     import scala.collection.JavaConverters.mapAsScalaMapConverter
 
     val stateOfResources = userStateMsg.getStateOfResources.asScala
@@ -97,8 +99,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
             processResourceEvents(
               realtimeMillis,
               virtualEvents,
-              userAgreementHistoryModel,
-              userStateMsg,
+              userStateModel,
               resourceMapping,
               realtimeMillis
             )
@@ -109,7 +110,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
   def findOrCalculateWorkingUserStateAtEndOfBillingMonth(
       processingTimeMillis: Long,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateModel: UserStateModel,
       billingMonthInfo: BillingMonthInfo,
       resourceMapping: JMap[String, ResourceTypeMsg],
       userStateRecorder: UserStateMsg ⇒ UserStateMsg
@@ -118,14 +119,14 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     def computeFullMonthBillingAndSaveState(): UserStateMsg = {
       val fullMonthUserState = replayFullMonthBilling(
         processingTimeMillis,
-        userAgreementHistoryModel,
+        userStateModel,
         billingMonthInfo,
         resourceMapping,
         userStateRecorder
       )
 
       val monthlyUserState0 = UserStateMsg.newBuilder(fullMonthUserState).
-        setIsFullBillingMonth(true).
+        setIsForFullMonth(true).
         setBillingYear(billingMonthInfo.year).
         setBillingMonth(billingMonthInfo.month). // FIXME What about the billingMonthDay?
         setOriginalID("").
@@ -139,8 +140,8 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       monthlyUserState1
     }
 
-    val userID = userAgreementHistoryModel.userID
-    val userCreationMillis = userAgreementHistoryModel.unsafeUserCreationMillis
+    val userID = userStateModel.userID
+    val userCreationMillis = userStateModel.unsafeUserCreationMillis
     val userCreationDateCalc = new MutableDateCalc(userCreationMillis)
     val billingMonthStartMillis = billingMonthInfo.monthStartMillis
     val billingMonthStopMillis = billingMonthInfo.monthStopMillis
@@ -213,17 +214,16 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
    * If needed, it may go back in time and recompute stuff.
    *
    * @param resourceEvent
-   * @param userStateMsg
    */
   def processResourceEvent(
       processingTimeMillis: Long,
       resourceEvent: ResourceEventMsg,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
-      userStateMsg: UserStateMsg,
+      userStateModel: UserStateModel,
       resourceMapping: JMap[String, ResourceTypeMsg],
       updateLatestMillis: Boolean
   ) {
-    require(userStateMsg ne null, "userStateMsg ne null")
+    val userStateMsg = userStateModel.userStateMsg
+    val userAgreementHistoryModel = userStateModel.userAgreementHistoryMsg
 
     val resourceName = resourceEvent.getResource
     val resourceTypeMsg = resourceMapping.get(resourceName)
@@ -251,8 +251,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       resourceTypeMsg,
       billingMonthInfo,
       resourcesChargingState,
-      userAgreementHistoryModel,
-      userStateMsg,
+      userStateModel,
       msg ⇒ userStateMsg.getWalletEntries.add(msg)
     )
     val m1 = TimeHelpers.nowMillis()
@@ -270,8 +269,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   def processResourceEvents(
       processingTimeMillis: Long,
       resourceEvents: Traversable[ResourceEventMsg],
-      userAgreementHistoryModel: UserAgreementHistoryModel,
-      userStateMsg: UserStateMsg,
+      userStateModel: UserStateModel,
       resourceMapping: JMap[String, ResourceTypeMsg],
       latestUpdateMillis: Long
   ): Unit = {
@@ -281,8 +279,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       processResourceEvent(
         processingTimeMillis,
         currentResourceEvent,
-        userAgreementHistoryModel,
-        userStateMsg,
+        userStateModel,
         resourceMapping,
         false
       )
@@ -291,13 +288,13 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     }
 
     if(_counter > 0) {
-      userStateMsg.setLatestUpdateMillis(latestUpdateMillis)
+      userStateModel.userStateMsg.setLatestUpdateMillis(latestUpdateMillis)
     }
   }
 
   def replayFullMonthBilling(
       processingTimeMillis: Long,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateModel: UserStateModel,
       billingMonthInfo: BillingMonthInfo,
       resourceMapping: JMap[String, ResourceTypeMsg],
       userStateRecorder: UserStateMsg ⇒ UserStateMsg
@@ -305,7 +302,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
     replayMonthChargingUpTo(
       processingTimeMillis,
-      userAgreementHistoryModel,
+      userStateModel,
       billingMonthInfo,
       billingMonthInfo.monthStopMillis,
       resourceMapping,
@@ -324,21 +321,23 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
    */
   def replayMonthChargingUpTo(
       processingTimeMillis: Long,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateModel: UserStateModel,
       billingMonthInfo: BillingMonthInfo,
       billingEndTimeMillis: Long,
       resourceMapping: JMap[String, ResourceTypeMsg],
       userStateRecorder: UserStateMsg ⇒ UserStateMsg
   ): UserStateMsg = {
 
+    val userAgreementHistoryMsg = userStateModel.userAgreementHistoryMsg
+
     val isFullMonthBilling = billingEndTimeMillis == billingMonthInfo.monthStopMillis
-    val userID = userAgreementHistoryModel.userID
+    val userID = userStateModel.userID
 
     // In order to replay the full month, we start with the state at the beginning of the month.
     val previousBillingMonthInfo = billingMonthInfo.previousMonth
     val userStateMsg = findOrCalculateWorkingUserStateAtEndOfBillingMonth(
       processingTimeMillis,
-      userAgreementHistoryModel,
+      userStateModel,
       previousBillingMonthInfo,
       resourceMapping,
       userStateRecorder
@@ -367,8 +366,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       processResourceEvent(
         processingTimeMillis,
         currentResourceEvent,
-        userAgreementHistoryModel,
-        userStateMsg,
+        userStateModel,
         resourceMapping,
         false
       )
index 9a85a7a..2697c92 100644 (file)
@@ -35,7 +35,7 @@
 
 package gr.grnet.aquarium.charging
 
-import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
+import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel}
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.MessageConstants
@@ -123,11 +123,12 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
        resourceType: ResourceTypeMsg,
        billingMonthInfo: BillingMonthInfo,
        resourcesChargingState: ResourcesChargingStateMsg,
-       userAgreementHistoryModel: UserAgreementHistoryModel,
-       userStateMsg: UserStateMsg,
+       userStateModel: UserStateModel,
        walletEntryRecorder: WalletEntryMsg ⇒ Unit
    ): (Int, Real) = {
 
+    val userStateMsg = userStateModel.userStateMsg
+
     // 1. Ensure proper initial state per resource and per instance
     ensureInitializedWorkingState(resourcesChargingState, resourceEvent)
 
@@ -148,7 +149,7 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
 
         val dummyFirstEventValue = "0.0" // TODO ? From configuration
 
-        val millis = userAgreementHistoryModel.agreementByTimeslot.headOption match {
+        val millis = userStateModel.agreementByTimeslot.headOption match {
           case None =>
             throw new AquariumInternalError("No agreement!!!") // FIXME Better explanation
           case Some((_,aggr)) =>
@@ -177,7 +178,7 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       Real(userStateMsg.getTotalCredits),
       previousEvent.getOccurredMillis,
       resourceEvent.getOccurredMillis,
-      userAgreementHistoryModel.agreementByTimeslot,
+      userStateModel.agreementByTimeslot,
       resourcesChargingStateDetails,
       resourceInstanceChargingState,
       aquarium,
index 6c62e6a..f9a1431 100644 (file)
@@ -36,7 +36,7 @@
 package gr.grnet.aquarium.charging
 
 import gr.grnet.aquarium.{Real, Aquarium}
-import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
+import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel}
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
@@ -83,10 +83,11 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
       resourcesChargingState: ResourcesChargingStateMsg,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
-      userStateMsg: UserStateMsg,
+      userStateModel: UserStateModel,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
   ): (Int, Real) = {
+    val userStateMsg = userStateModel.userStateMsg
+
     // The credits are given in the value
     // But we cannot just apply them, since we also need to take into account the unit price.
     // Normally, the unit price is 1.0 but we have the flexibility to allow more stuff).
@@ -108,7 +109,7 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       Real(userStateMsg.getTotalCredits),
       resourceEvent.getOccurredMillis,
       resourceEvent.getOccurredMillis + 1, // single point in time
-      userAgreementHistoryModel.agreementByTimeslot,
+      userStateModel.agreementByTimeslot,
       resourcesChargingStateDetails,
       resourceInstanceChargingState,
       aquarium,
index 7cf2f27..9bf585a 100644 (file)
@@ -37,7 +37,7 @@ package gr.grnet.aquarium.charging
 
 import VMChargingBehavior.SelectorLabels.PowerStatus
 import VMChargingBehavior.Selectors.Power
-import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
+import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel}
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.MessageConstants
@@ -138,11 +138,12 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
       resourcesChargingState: ResourcesChargingStateMsg,
-      userAgreementHistoryModel: UserAgreementHistoryModel,
-      userStateMsg: UserStateMsg,
+      userStateModel: UserStateModel,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
   ): (Int, Real) = {
 
+    val userStateMsg = userStateModel.userStateMsg
+
     // 1. Ensure proper initial state per resource and per instance
     ensureInitializedWorkingState(resourcesChargingState,resourceEvent)
 
@@ -169,7 +170,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
           Real(userStateMsg.getTotalCredits),
           previousEvent.getOccurredMillis,
           resourceEvent.getOccurredMillis,
-          userAgreementHistoryModel.agreementByTimeslot,
+          userStateModel.agreementByTimeslot,
           resourcesChargingStateDetails,
           resourceInstanceChargingState,
           aquarium,
index 2c30a5d..f56b0e1 100644 (file)
@@ -47,34 +47,31 @@ import gr.grnet.aquarium.message.avro.{MessageFactory, MessageHelpers, ModelFact
  * @author Christos KK Loverdos <loverdos@gmail.com>
  */
 
-final class UserAgreementHistoryModel(msg: UserAgreementHistoryMsg) {
+final class UserAgreementHistoryModel(val userAgreementHistoryMsg: UserAgreementHistoryMsg) {
 
   private[this] var _latestIMEventOccurredMillis = 0L
+  private[this] var _userCreationIMEventMsgOpt: Option[IMEventMsg] = None
 
-  private[this] var (_userAgreementModels, _userCreationIMEventMsgOpt): (immutable.SortedSet[UserAgreementModel], Option[IMEventMsg]) = {
+  private[this] var _userAgreementModels: immutable.SortedSet[UserAgreementModel] = {
     var userAgreementModels = immutable.SortedSet[UserAgreementModel]()
-    var userCreationIMEventMsg: Option[IMEventMsg] = None
-    val userAgreements = msg.getAgreements.iterator()
+    val userAgreements = userAgreementHistoryMsg.getAgreements.iterator()
     while(userAgreements.hasNext) {
       val userAgreement = userAgreements.next()
       val userAgreementModel = ModelFactory.newUserAgreementModel(userAgreement)
       userAgreementModels += userAgreementModel
 
-      userAgreement.getRelatedIMEventMsg match {
-        case null ⇒
-
-        case msg ⇒
-          if(MessageHelpers.isIMEventCreate(msg)) {
-            userCreationIMEventMsg = Some(msg)
-          }
-      }
-
+      checkUserCreationIMEvent(userAgreement.getRelatedIMEventMsg)
       checkLatestIMEventOccurredMillis(userAgreement.getRelatedIMEventMsg)
     }
 
-    (userAgreementModels, userCreationIMEventMsg)
+    userAgreementModels
   }
 
+  private[this] def checkUserCreationIMEvent(imEvent: IMEventMsg) {
+    if(MessageHelpers.isIMEventCreate(imEvent)) {
+      this._userCreationIMEventMsgOpt = Some(imEvent)
+    }
+  }
   private[this] def checkLatestIMEventOccurredMillis(imEvent: IMEventMsg) {
     if(imEvent ne null) {
       if(this._latestIMEventOccurredMillis < imEvent.getOccurredMillis) {
@@ -83,28 +80,35 @@ final class UserAgreementHistoryModel(msg: UserAgreementHistoryMsg) {
     }
   }
 
-  def userID = this.msg.getUserID
+  private[this] def updateOtherVars(imEvent: IMEventMsg) {
+    checkUserCreationIMEvent(imEvent)
+    checkLatestIMEventOccurredMillis(imEvent)
+  }
+
+  def userID = this.userAgreementHistoryMsg.getUserID
 
   def latestIMEventOccurredMillis = this._latestIMEventOccurredMillis
 
   def hasUserCreationEvent = this._userCreationIMEventMsgOpt.isDefined
 
-  def userCreationIMEvent = this._userCreationIMEventMsgOpt
+  def userCreationIMEventOpt = this._userCreationIMEventMsgOpt
 
   def unsafeUserCreationIMEvent = this._userCreationIMEventMsgOpt.get
 
   def unsafeUserCreationMillis = unsafeUserCreationIMEvent.getOccurredMillis
 
-  def size: Int = msg.getAgreements.size()
+  def size: Int = userAgreementHistoryMsg.getAgreements.size()
 
   def agreementByTimeslot: immutable.SortedMap[Timeslot, UserAgreementModel] = {
     immutable.TreeMap(_userAgreementModels.map(ag ⇒ (ag.timeslot, ag)).toSeq: _*)
   }
 
   def insertUserAgreementModel(userAgreement: UserAgreementModel) {
-    MessageHelpers.insertUserAgreement(this.msg, userAgreement.msg)
+    MessageHelpers.insertUserAgreement(this.userAgreementHistoryMsg, userAgreement.msg)
+
     this._userAgreementModels += userAgreement
-    checkLatestIMEventOccurredMillis(userAgreement.msg.getRelatedIMEventMsg)
+
+    updateOtherVars(userAgreement.msg.getRelatedIMEventMsg)
   }
 
   def insertUserAgreementMsg(userAgreementMsg: UserAgreementMsg) {
@@ -124,12 +128,6 @@ final class UserAgreementHistoryModel(msg: UserAgreementHistoryMsg) {
     _userAgreementModels.lastOption
   }
 
-  override def toString = msg.toString
-
-//  def agreementInEffectWhen(whenMillis: Long): Option[UserAgreementModel] = {
-//    agreements.to(
-//      UserAgreementModel("", None, whenMillis, Long.MaxValue, "", PolicyDefinedFullPriceTableRef())
-//    ).lastOption
-//  }
+  override def toString = userAgreementHistoryMsg.toString
 }
 
diff --git a/src/main/scala/gr/grnet/aquarium/charging/state/UserStateBootstrap.scala b/src/main/scala/gr/grnet/aquarium/charging/state/UserStateBootstrap.scala
deleted file mode 100644 (file)
index 7327d6e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- *   1. Redistributions of source code must retain the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer in the documentation and/or other materials
- *      provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- */
-
-package gr.grnet.aquarium.charging.state
-
-import gr.grnet.aquarium.policy.UserAgreementModel
-import gr.grnet.aquarium.Real
-
-/**
- * This is used to bootstrap the [[gr.grnet.aquarium.charging.state.UserStateModel]].
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>
- */
-
-final case class UserStateBootstrap(
-    initialAgreement: UserAgreementModel,
-    initialCredits: Real
-) {
-  def userID = initialAgreement.msg.getUserID
-
-  def userCreationMillis = initialAgreement.msg.getValidFromMillis
-
-  override def toString = "userID = %s".format(userID)
-}
index ff8c25d..99f8e8d 100644 (file)
 
 package gr.grnet.aquarium.charging.state
 
-import gr.grnet.aquarium.message.avro.gen.UserStateMsg
+import gr.grnet.aquarium.message.avro.gen.{UserAgreementMsg, IMEventMsg, UserAgreementHistoryMsg, UserStateMsg}
 import gr.grnet.aquarium.Real
+import scala.collection.immutable
+import gr.grnet.aquarium.policy.UserAgreementModel
+import gr.grnet.aquarium.message.avro.{MessageFactory, MessageHelpers, ModelFactory}
+import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 
 /**
  *
- * A wrapper around [[gr.grnet.aquarium.message.avro.gen.UserStateMsg]] with convenient (sorted)
+ * A wrapper around [[gr.grnet.aquarium.message.avro.gen.UserStateMsg]] and
+ * [[]] with convenient (sorted)
  * user agreement history.
  *
  * @author Christos KK Loverdos <loverdos@gmail.com>
  */
 
-final class UserStateModel(msg: UserStateMsg) {
+final class UserStateModel(
+    private[this] var _userStateMsg: UserStateMsg,
+    private[this] var _userAgreementHistoryMsg: UserAgreementHistoryMsg
+) {
+  require(this._userStateMsg ne null, "this._userStateMsg ne null")
+  require(this._userAgreementHistoryMsg ne null, "this._userAgreementHistoryMsg ne null")
 
-  def userID = msg.getUserID
+  private[this] var _latestIMEventOccurredMillis = 0L
+  private[this] var _userCreationIMEventMsgOpt: Option[IMEventMsg] = None
 
-  def latestResourceEventOccurredMillis = this.msg.getLatestResourceEventOccurredMillis
+  private[this] var _userAgreementModels: immutable.SortedSet[UserAgreementModel] = {
+    var userAgreementModels = immutable.SortedSet[UserAgreementModel]()
+    val userAgreements = _userAgreementHistoryMsg.getAgreements.iterator()
+    while(userAgreements.hasNext) {
+      val userAgreement = userAgreements.next()
+      val userAgreementModel = ModelFactory.newUserAgreementModel(userAgreement)
+      userAgreementModels += userAgreementModel
 
-  @inline final def totalCredits: Real = {
-    Real(msg.getTotalCredits)
+      checkUserCreationIMEvent(userAgreement.getRelatedIMEventMsg)
+      checkLatestIMEventOccurredMillis(userAgreement.getRelatedIMEventMsg)
+    }
+
+    userAgreementModels
+  }
+
+  private[this] def checkUserCreationIMEvent(imEvent: IMEventMsg) {
+    if(MessageHelpers.isIMEventCreate(imEvent)) {
+      this._userCreationIMEventMsgOpt = Some(imEvent)
+    }
+  }
+  private[this] def checkLatestIMEventOccurredMillis(imEvent: IMEventMsg) {
+    if(imEvent ne null) {
+      if(this._latestIMEventOccurredMillis < imEvent.getOccurredMillis) {
+        this._latestIMEventOccurredMillis = imEvent.getOccurredMillis
+      }
+    }
+  }
+
+  private[this] def updateOtherVars(imEvent: IMEventMsg) {
+    checkUserCreationIMEvent(imEvent)
+    checkLatestIMEventOccurredMillis(imEvent)
+  }
+
+  def userID = this._userAgreementHistoryMsg.getUserID
+
+  def latestIMEventOccurredMillis = this._latestIMEventOccurredMillis
+
+  def hasUserCreationEvent = this._userCreationIMEventMsgOpt.isDefined
+
+  def userCreationIMEventOpt = this._userCreationIMEventMsgOpt
+
+  def unsafeUserCreationIMEvent = this._userCreationIMEventMsgOpt.get
+
+  def unsafeUserCreationMillis = unsafeUserCreationIMEvent.getOccurredMillis
+
+  def size: Int = _userAgreementHistoryMsg.getAgreements.size()
+
+  def userStateMsg = this._userStateMsg
+
+  def updateUserStateMsg(msg: UserStateMsg) {
+    this._userStateMsg = msg
+  }
+
+  def userAgreementHistoryMsg = this._userAgreementHistoryMsg
+
+  def updateUserAgreementHistoryMsg(msg: UserAgreementHistoryMsg) {
+    this._userAgreementHistoryMsg = msg
   }
 
-  override def toString = msg.toString
-
-//  def newForImplicitEndsAsPreviousEvents(
-//      previousResourceEvents: mutable.Map[(String, String), ResourceEventModel]
-//  ) = {
-//
-//    new WorkingUserState(
-//      this.userID,
-//      this.parentUserStateIDInStore,
-//      this.chargingReason,
-//      this.resourceTypesMap,
-//      previousResourceEvents,
-//      this.implicitlyIssuedStartEventOfResourceInstance,
-//      this.accumulatingAmountOfResourceInstance,
-//      this.chargingDataOfResourceInstance,
-//      this.totalCredits,
-//      this.workingAgreementHistory,
-//      this.latestUpdateMillis,
-//      this.latestResourceEventOccurredMillis,
-//      this.billingPeriodOutOfSyncResourceEventsCounter,
-//      this.walletEntries
-//    )
-//  }
-
-//  def getChargingDataForResourceEvent(resourceAndInstanceInfo: (String, String)): mutable.Map[String, Any] = {
-//    chargingDataOfResourceInstance.get(resourceAndInstanceInfo) match {
-//      case Some(map) ⇒
-//        map
-//
-//      case None ⇒
-//        val map = mutable.Map[String, Any]()
-//        chargingDataOfResourceInstance(resourceAndInstanceInfo) = map
-//        map
-//
-//    }
-//  }
-
-//  def setChargingDataForResourceEvent(
-//      resourceAndInstanceInfo: (String, String),
-//      data: mutable.Map[String, Any]
-//  ): Unit = {
-//    chargingDataOfResourceInstance(resourceAndInstanceInfo) = data
-//  }
-
-  /**
-  * Find those events from `implicitlyIssuedStartEvents` and `previousResourceEvents` that will generate implicit
-  * end events along with those implicitly issued events. Before returning, remove the events that generated the
-  * implicit ends from the internal state of this instance.
-  *
-  * @see [[gr.grnet.aquarium.charging.ChargingBehavior]]
-  */
-// def findAndRemoveGeneratorsOfImplicitEndEvents(
-//     chargingBehaviorOfResourceType: ResourceType ⇒ ChargingBehavior,
-//     /**
-//      * The `occurredMillis` that will be recorded in the synthetic implicit OFFs.
-//      * Normally, this will be the end of a billing month.
-//      */
-//     newOccuredMillis: Long
-// ): (List[ResourceEventModel], List[ResourceEventModel]) = {
-//
-//   val buffer = mutable.ListBuffer[(ResourceEventModel, ResourceEventModel)]()
-//   val checkSet = mutable.Set[ResourceEventModel]()
-//
-//   def doItFor(map: mutable.Map[(String, String), ResourceEventModel]): Unit = {
-//     val resourceEvents = map.valuesIterator
-//     for {
-//       resourceEvent ← resourceEvents
-//       resourceType ← resourceTypesMap.get(resourceEvent.safeResource)
-//       chargingBehavior = chargingBehaviorOfResourceType.apply(resourceType)
-//     } {
-//       if(chargingBehavior.supportsImplicitEvents) {
-//         if(chargingBehavior.mustConstructImplicitEndEventFor(resourceEvent)) {
-//           val implicitEnd = chargingBehavior.constructImplicitEndEventFor(resourceEvent, newOccuredMillis)
-//
-//           if(!checkSet.contains(resourceEvent)) {
-//             checkSet.add(resourceEvent)
-//             buffer append ((resourceEvent, implicitEnd))
-//           }
-//
-//           // remove it anyway
-//           map.remove((resourceEvent.safeResource, resourceEvent.safeInstanceID))
-//         }
-//       }
-//     }
-//   }
-//
-//   doItFor(previousEventOfResourceInstance) // we give priority for previous events
-//   doItFor(implicitlyIssuedStartEventOfResourceInstance) // ... over implicitly issued ones ...
-//
-//   (buffer.view.map(_._1).toList, buffer.view.map(_._2).toList)
-// }
+  def agreementByTimeslot: immutable.SortedMap[Timeslot, UserAgreementModel] = {
+    immutable.TreeMap(_userAgreementModels.map(ag ⇒ (ag.timeslot, ag)).toSeq: _*)
+  }
+
+  def insertUserAgreementModel(userAgreement: UserAgreementModel) {
+    MessageHelpers.insertUserAgreement(this._userAgreementHistoryMsg, userAgreement.msg)
+
+    this._userAgreementModels += userAgreement
+
+    updateOtherVars(userAgreement.msg.getRelatedIMEventMsg)
+  }
+
+  def insertUserAgreementMsg(userAgreementMsg: UserAgreementMsg) {
+    insertUserAgreementModel(ModelFactory.newUserAgreementModel(userAgreementMsg))
+  }
+
+  def insertUserAgreementMsgFromIMEvent(imEvent: IMEventMsg) {
+    val userAgreementMsg = MessageFactory.newUserAgreementFromIMEventMsg(imEvent)
+    insertUserAgreementMsg(userAgreementMsg)
+  }
+
+  def oldestAgreementModel: Option[UserAgreementModel] = {
+    _userAgreementModels.headOption
+  }
+
+  def newestAgreementModel: Option[UserAgreementModel] = {
+    _userAgreementModels.lastOption
+  }
+
+  def latestResourceEventOccurredMillis = this._userStateMsg.getLatestResourceEventOccurredMillis
+
+  @inline final def totalCreditsAsReal: Real = Real(this._userStateMsg.getTotalCredits)
+
+  @inline final def totalCredits: String = this._userStateMsg.getTotalCredits
+
+  override def toString = _userStateMsg.toString
+
 }
index 9d34fef..dbf7dd8 100644 (file)
@@ -360,6 +360,15 @@ object MessageFactory {
       build()
   }
 
+  /**
+   * Creates the initial (from the UserActor's perspective) user state.
+   * This may not be the very first user state ever, so we do not set `isFirst`.
+   * @param userID
+   * @param initialCredits
+   * @param occurredMillis
+   * @param originalID
+   * @return
+   */
   def newInitialUserStateMsg(
       userID: String,
       initialCredits: Real,
@@ -379,8 +388,8 @@ object MessageFactory {
     msg.setLatestUpdateMillis(java.lang.Long.valueOf(occurredMillis))
     msg.setInStoreID(null)
     msg.setOriginalID(originalID)
-    msg.setStateOfResources(new java.util.HashMap())
-    msg.setWalletEntries(new java.util.ArrayList[WalletEntryMsg]())
+    msg.setStateOfResources(newJMap)
+    msg.setWalletEntries(newJList)
     msg
   }
 }
index 6fbd46f..6ee2d79 100644 (file)
@@ -48,6 +48,7 @@ import gr.grnet.aquarium.policy.UserAgreementModel
 import gr.grnet.aquarium.policy._
 import scala.collection.JavaConverters.asScalaBufferConverter
 import scala.collection.JavaConverters.mapAsScalaMapConverter
+import gr.grnet.aquarium.Real
 
 /**
  * Provides helper methods that construct model objects, usually from their avro message counterparts.
@@ -191,7 +192,14 @@ object ModelFactory {
     new UserAgreementHistoryModel(historyMsg)
   }
 
-  def newUserStateModel(msg: UserStateMsg): UserStateModel = {
-    new UserStateModel(msg)
+  def newInitialUserStateModel(
+      userID: String,
+      initialCredits: Real,
+      occurredMillis: Long
+  ): UserStateModel = {
+    val userStateMsg = MessageFactory.newInitialUserStateMsg(userID, initialCredits, occurredMillis)
+    val userAgreementHistoryMsg = MessageFactory.newUserAgreementHistoryMsg(userID)
+
+    new UserStateModel(userStateMsg, userAgreementHistoryMsg)
   }
 }
index 80caf9c..f919fa8 100644 (file)
@@ -112,7 +112,7 @@ extends StoreProvider
   def findLatestUserStateForFullMonthBilling(userID: String, bmi: BillingMonthInfo) = {
     _userStates.filter { userState ⇒
       userState.getUserID == userID &&
-      userState.getIsFullBillingMonth &&
+      userState.getIsForFullMonth &&
       userState.getBillingYear == bmi.year &&
       userState.getBillingMonth == bmi.month
     }.lastOption
index c12d5a4..1907ec7 100644 (file)
@@ -177,7 +177,7 @@ class MongoDBStore(
   def findLatestUserStateForFullMonthBilling(userID: String, bmi: BillingMonthInfo) = {
     val query = new BasicDBObjectBuilder().
       add(MongoDBStore.JsonNames.userID, userID).
-      add(MongoDBStore.JsonNames.isFullBillingMonth, true).
+      add(MongoDBStore.JsonNames.isForFullMonth, true).
       add(MongoDBStore.JsonNames.billingYear, bmi.year).
       add(MongoDBStore.JsonNames.billingMonth, bmi.month).
       get()
@@ -219,7 +219,7 @@ class MongoDBStore(
       add(MongoDBStore.JsonNames.payload, AvroHelpers.bytesOfSpecificRecord(event)).
       add(MongoDBStore.JsonNames.userID, event.getUserID).
       add(MongoDBStore.JsonNames.occurredMillis, event.getOccurredMillis).
-      add(MongoDBStore.JsonNames.isFullBillingMonth, event.getIsFullBillingMonth).
+      add(MongoDBStore.JsonNames.isForFullMonth, event.getIsForFullMonth).
       add(MongoDBStore.JsonNames.billingYear, event.getBillingYear).
       add(MongoDBStore.JsonNames.billingMonth, event.getBillingMonth).
       add(MongoDBStore.JsonNames.billingMonthDay, event.getBillingMonthDay).
index d717f35..1986456 100644 (file)
@@ -52,7 +52,7 @@ final object JsonNames {
   final val billingMonth = "billingMonth"
   final val billingMonthDay = "billingMonthDay"
   final val billingYear = "billingYear"
-  final val isFullBillingMonth = "isFullBillingMonth"
+  final val isForFullMonth = "isForFullMonth"
   final val eventType = "eventType"
   final val eventVersion = "eventVersion"
   final val userID = "userID"