WIP: New state machine for message processing
authorChristos KK Loverdos <loverdos@gmail.com>
Mon, 24 Sep 2012 15:38:00 +0000 (18:38 +0300)
committerChristos KK Loverdos <loverdos@gmail.com>
Mon, 24 Sep 2012 15:38:00 +0000 (18:38 +0300)
26 files changed:
src/main/avro/aquarium-policy.avdl
src/main/avro/aquarium-user-state.avdl
src/main/java/gr/grnet/aquarium/message/avro/gen/AquariumPolicy.java
src/main/java/gr/grnet/aquarium/message/avro/gen/AquariumUserState.java
src/main/java/gr/grnet/aquarium/message/avro/gen/PolicyMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/UserAgreementHistoryMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/UserStateMsg.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
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/MessageHelpers.scala
src/main/scala/gr/grnet/aquarium/message/avro/ModelFactory.scala
src/main/scala/gr/grnet/aquarium/message/avro/OrderingHelpers.scala
src/main/scala/gr/grnet/aquarium/policy/PolicyModel.scala
src/main/scala/gr/grnet/aquarium/store/UserStateStore.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/store/mongodb/MongoDBStoreProvider.scala

index 9f7acde..5c77f6b 100644 (file)
@@ -72,7 +72,7 @@ protocol AquariumPolicy {
     union {string, null} parentID; // FIXME: parentOriginalID and parentInStoreID
     long validFromMillis;
     long validToMillis;
-    array<ResourceTypeMsg> resourceTypes; // the known resource types
+    map<ResourceTypeMsg> resourceMapping; // Map[ResourceTypeMsg.name.type, ResourceTypeMsg] the known resource types
     array<string> chargingBehaviors;      // the known charging behavior implementations
     map<FullPriceTableMsg> roleMapping;   // the pricing "plan" per role
   }
index 40334a4..32cfdb0 100644 (file)
@@ -76,6 +76,7 @@ protocol AquariumUserState {
     string userID;
     long latestOccurredMillis; // the latest occurredMillis of all underlying agreements
     long latestValidFromMillis; // the latest validFromMillis of all underlying agreements
+    long userCreationTimeMillis = 0;
     array<UserAgreementMsg> agreements;
   }
 
@@ -118,10 +119,9 @@ protocol AquariumUserState {
     long occurredMillis; // When we created the event
     union {string, null} parentOriginalID;
     union {string, null} parentInStoreID;
-    map<ResourceTypeMsg> resourceTypesMap; // Map[ResourceTypeMsg.name.type, ResourceTypeMsg]
+//    map<ResourceTypeMsg> resourceTypesMap; // Map[ResourceTypeMsg.name.type, ResourceTypeMsg]
     map<ResourcesChargingStateMsg> stateOfResources; // Map[ResourceTypeMsg.name.type, ]
     double totalCredits = 0.0;
-    UserAgreementHistoryMsg agreementHistory;
     long latestUpdateMillis; // // last update of this working user state
     long latestResourceEventOccurredMillis;
     long billingPeriodOutOfSyncResourceEventsCounter = 0;
index eb5f67c..62f534d 100644 (file)
@@ -7,7 +7,7 @@ package gr.grnet.aquarium.message.avro.gen;
 
 @SuppressWarnings("all")
 public interface AquariumPolicy {
-  public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"AquariumPolicy\",\"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\":\"double\"},{\"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\":\"resourceTypes\",\"type\":{\"type\":\"array\",\"items\":\"ResourceTypeMsg\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":\"FullPriceTableMsg\",\"avro.java.string\":\"String\"}}]}],\"messages\":{}}");
+  public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"AquariumPolicy\",\"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\":\"double\"},{\"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\"}}]}],\"messages\":{}}");
 
   @SuppressWarnings("all")
   public interface Callback extends AquariumPolicy {
index a5bc1c6..3b65052 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\":\"double\"},{\"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\":\"resourceTypes\",\"type\":{\"type\":\"array\",\"items\":\"ResourceTypeMsg\"}},{\"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\":\"double\"},{\"name\":\"oldAccumulatingAmount\",\"type\":\"double\"},{\"name\":\"previousValue\",\"type\":\"double\"},{\"name\":\"currentValue\",\"type\":\"double\"}]},{\"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\":\"agreements\",\"type\":{\"type\":\"array\",\"items\":\"UserAgreementMsg\"}}]},{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":\"double\"},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":\"double\",\"default\":0.0}]},{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":\"double\"},{\"name\":\"oldTotalCredits\",\"type\":\"double\"},{\"name\":\"newTotalCredits\",\"type\":\"double\"},{\"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\":\"resourceTypesMap\",\"type\":{\"type\":\"map\",\"values\":\"ResourceTypeMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":\"ResourcesChargingStateMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":\"double\",\"default\":0.0},{\"name\":\"agreementHistory\",\"type\":\"UserAgreementHistoryMsg\"},{\"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\":\"double\"},{\"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\":\"double\"},{\"name\":\"oldAccumulatingAmount\",\"type\":\"double\"},{\"name\":\"previousValue\",\"type\":\"double\"},{\"name\":\"currentValue\",\"type\":\"double\"}]},{\"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\":\"double\"},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":\"double\",\"default\":0.0}]},{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":\"double\"},{\"name\":\"oldTotalCredits\",\"type\":\"double\"},{\"name\":\"newTotalCredits\",\"type\":\"double\"},{\"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\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":\"ResourcesChargingStateMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":\"double\",\"default\":0.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\":{}}");
 
   @SuppressWarnings("all")
   public interface Callback extends AquariumUserState {
index d07e7f7..61334f1 100644 (file)
@@ -6,13 +6,13 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class PolicyMsg 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\":\"PolicyMsg\",\"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\":\"parentID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"resourceTypes\",\"type\":{\"type\":\"array\",\"items\":{\"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\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":{\"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\":\"double\"},{\"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\"}}]},\"avro.java.string\":\"String\"}}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"PolicyMsg\",\"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\":\"parentID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"resourceMapping\",\"type\":{\"type\":\"map\",\"values\":{\"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\"}}]},\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":{\"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\":\"double\"},{\"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\"}}]},\"avro.java.string\":\"String\"}}]}");
   @Deprecated public java.lang.String originalID;
   @Deprecated public java.lang.String inStoreID;
   @Deprecated public java.lang.String parentID;
   @Deprecated public long validFromMillis;
   @Deprecated public long validToMillis;
-  @Deprecated public java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> resourceTypes;
+  @Deprecated public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> resourceMapping;
   @Deprecated public java.util.List<java.lang.String> chargingBehaviors;
   @Deprecated public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.FullPriceTableMsg> roleMapping;
   public org.apache.avro.Schema getSchema() { return SCHEMA$; }
@@ -24,7 +24,7 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
     case 2: return parentID;
     case 3: return validFromMillis;
     case 4: return validToMillis;
-    case 5: return resourceTypes;
+    case 5: return resourceMapping;
     case 6: return chargingBehaviors;
     case 7: return roleMapping;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
@@ -39,7 +39,7 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
     case 2: parentID = (java.lang.String)value$; break;
     case 3: validFromMillis = (java.lang.Long)value$; break;
     case 4: validToMillis = (java.lang.Long)value$; break;
-    case 5: resourceTypes = (java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>)value$; break;
+    case 5: resourceMapping = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>)value$; break;
     case 6: chargingBehaviors = (java.util.List<java.lang.String>)value$; break;
     case 7: roleMapping = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.FullPriceTableMsg>)value$; break;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
@@ -122,18 +122,18 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
   }
 
   /**
-   * Gets the value of the 'resourceTypes' field.
+   * Gets the value of the 'resourceMapping' field.
    */
-  public java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> getResourceTypes() {
-    return resourceTypes;
+  public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> getResourceMapping() {
+    return resourceMapping;
   }
 
   /**
-   * Sets the value of the 'resourceTypes' field.
+   * Sets the value of the 'resourceMapping' field.
    * @param value the value to set.
    */
-  public void setResourceTypes(java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> value) {
-    this.resourceTypes = value;
+  public void setResourceMapping(java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> value) {
+    this.resourceMapping = value;
   }
 
   /**
@@ -192,7 +192,7 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
     private java.lang.String parentID;
     private long validFromMillis;
     private long validToMillis;
-    private java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> resourceTypes;
+    private java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> resourceMapping;
     private java.util.List<java.lang.String> chargingBehaviors;
     private java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.FullPriceTableMsg> roleMapping;
 
@@ -229,8 +229,8 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
         this.validToMillis = (java.lang.Long) data().deepCopy(fields()[4].schema(), other.validToMillis);
         fieldSetFlags()[4] = true;
       }
-      if (isValidValue(fields()[5], other.resourceTypes)) {
-        this.resourceTypes = (java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>) data().deepCopy(fields()[5].schema(), other.resourceTypes);
+      if (isValidValue(fields()[5], other.resourceMapping)) {
+        this.resourceMapping = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>) data().deepCopy(fields()[5].schema(), other.resourceMapping);
         fieldSetFlags()[5] = true;
       }
       if (isValidValue(fields()[6], other.chargingBehaviors)) {
@@ -366,27 +366,27 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
       return this;
     }
 
-    /** Gets the value of the 'resourceTypes' field */
-    public java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> getResourceTypes() {
-      return resourceTypes;
+    /** Gets the value of the 'resourceMapping' field */
+    public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> getResourceMapping() {
+      return resourceMapping;
     }
     
-    /** Sets the value of the 'resourceTypes' field */
-    public gr.grnet.aquarium.message.avro.gen.PolicyMsg.Builder setResourceTypes(java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> value) {
+    /** Sets the value of the 'resourceMapping' field */
+    public gr.grnet.aquarium.message.avro.gen.PolicyMsg.Builder setResourceMapping(java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> value) {
       validate(fields()[5], value);
-      this.resourceTypes = value;
+      this.resourceMapping = value;
       fieldSetFlags()[5] = true;
       return this; 
     }
     
-    /** Checks whether the 'resourceTypes' field has been set */
-    public boolean hasResourceTypes() {
+    /** Checks whether the 'resourceMapping' field has been set */
+    public boolean hasResourceMapping() {
       return fieldSetFlags()[5];
     }
     
-    /** Clears the value of the 'resourceTypes' field */
-    public gr.grnet.aquarium.message.avro.gen.PolicyMsg.Builder clearResourceTypes() {
-      resourceTypes = null;
+    /** Clears the value of the 'resourceMapping' field */
+    public gr.grnet.aquarium.message.avro.gen.PolicyMsg.Builder clearResourceMapping() {
+      resourceMapping = null;
       fieldSetFlags()[5] = false;
       return this;
     }
@@ -450,7 +450,7 @@ public class PolicyMsg extends org.apache.avro.specific.SpecificRecordBase imple
         record.parentID = fieldSetFlags()[2] ? this.parentID : (java.lang.String) defaultValue(fields()[2]);
         record.validFromMillis = fieldSetFlags()[3] ? this.validFromMillis : (java.lang.Long) defaultValue(fields()[3]);
         record.validToMillis = fieldSetFlags()[4] ? this.validToMillis : (java.lang.Long) defaultValue(fields()[4]);
-        record.resourceTypes = fieldSetFlags()[5] ? this.resourceTypes : (java.util.List<gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>) defaultValue(fields()[5]);
+        record.resourceMapping = fieldSetFlags()[5] ? this.resourceMapping : (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>) defaultValue(fields()[5]);
         record.chargingBehaviors = fieldSetFlags()[6] ? this.chargingBehaviors : (java.util.List<java.lang.String>) defaultValue(fields()[6]);
         record.roleMapping = fieldSetFlags()[7] ? this.roleMapping : (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.FullPriceTableMsg>) defaultValue(fields()[7]);
         return record;
index 05e4dc0..ab67b45 100644 (file)
@@ -6,12 +6,13 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class UserAgreementHistoryMsg 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\":\"UserAgreementHistoryMsg\",\"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\":\"latestOccurredMillis\",\"type\":\"long\"},{\"name\":\"latestValidFromMillis\",\"type\":\"long\"},{\"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\":\"double\"},{\"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\":{\"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\"}}]},\"null\"]}]}}}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"UserAgreementHistoryMsg\",\"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\":\"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\":\"double\"},{\"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\":{\"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\"}}]},\"null\"]}]}}}]}");
   @Deprecated public java.lang.String originalID;
   @Deprecated public java.lang.String inStoreID;
   @Deprecated public java.lang.String userID;
   @Deprecated public long latestOccurredMillis;
   @Deprecated public long latestValidFromMillis;
+  @Deprecated public long userCreationTimeMillis;
   @Deprecated public java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg> agreements;
   public org.apache.avro.Schema getSchema() { return SCHEMA$; }
   // Used by DatumWriter.  Applications should not call. 
@@ -22,7 +23,8 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
     case 2: return userID;
     case 3: return latestOccurredMillis;
     case 4: return latestValidFromMillis;
-    case 5: return agreements;
+    case 5: return userCreationTimeMillis;
+    case 6: return agreements;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -35,7 +37,8 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
     case 2: userID = (java.lang.String)value$; break;
     case 3: latestOccurredMillis = (java.lang.Long)value$; break;
     case 4: latestValidFromMillis = (java.lang.Long)value$; break;
-    case 5: agreements = (java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg>)value$; break;
+    case 5: userCreationTimeMillis = (java.lang.Long)value$; break;
+    case 6: agreements = (java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg>)value$; break;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -116,6 +119,21 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
   }
 
   /**
+   * Gets the value of the 'userCreationTimeMillis' field.
+   */
+  public java.lang.Long getUserCreationTimeMillis() {
+    return userCreationTimeMillis;
+  }
+
+  /**
+   * Sets the value of the 'userCreationTimeMillis' field.
+   * @param value the value to set.
+   */
+  public void setUserCreationTimeMillis(java.lang.Long value) {
+    this.userCreationTimeMillis = value;
+  }
+
+  /**
    * Gets the value of the 'agreements' field.
    */
   public java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg> getAgreements() {
@@ -156,6 +174,7 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
     private java.lang.String userID;
     private long latestOccurredMillis;
     private long latestValidFromMillis;
+    private long userCreationTimeMillis;
     private java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg> agreements;
 
     /** Creates a new Builder */
@@ -191,10 +210,14 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
         this.latestValidFromMillis = (java.lang.Long) data().deepCopy(fields()[4].schema(), other.latestValidFromMillis);
         fieldSetFlags()[4] = true;
       }
-      if (isValidValue(fields()[5], other.agreements)) {
-        this.agreements = (java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg>) data().deepCopy(fields()[5].schema(), other.agreements);
+      if (isValidValue(fields()[5], other.userCreationTimeMillis)) {
+        this.userCreationTimeMillis = (java.lang.Long) data().deepCopy(fields()[5].schema(), other.userCreationTimeMillis);
         fieldSetFlags()[5] = true;
       }
+      if (isValidValue(fields()[6], other.agreements)) {
+        this.agreements = (java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg>) data().deepCopy(fields()[6].schema(), other.agreements);
+        fieldSetFlags()[6] = true;
+      }
     }
 
     /** Gets the value of the 'originalID' field */
@@ -320,6 +343,30 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
       return this;
     }
 
+    /** Gets the value of the 'userCreationTimeMillis' field */
+    public java.lang.Long getUserCreationTimeMillis() {
+      return userCreationTimeMillis;
+    }
+    
+    /** Sets the value of the 'userCreationTimeMillis' field */
+    public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg.Builder setUserCreationTimeMillis(long value) {
+      validate(fields()[5], value);
+      this.userCreationTimeMillis = value;
+      fieldSetFlags()[5] = true;
+      return this; 
+    }
+    
+    /** Checks whether the 'userCreationTimeMillis' field has been set */
+    public boolean hasUserCreationTimeMillis() {
+      return fieldSetFlags()[5];
+    }
+    
+    /** Clears the value of the 'userCreationTimeMillis' field */
+    public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg.Builder clearUserCreationTimeMillis() {
+      fieldSetFlags()[5] = false;
+      return this;
+    }
+
     /** Gets the value of the 'agreements' field */
     public java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg> getAgreements() {
       return agreements;
@@ -327,21 +374,21 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
     
     /** Sets the value of the 'agreements' field */
     public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg.Builder setAgreements(java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg> value) {
-      validate(fields()[5], value);
+      validate(fields()[6], value);
       this.agreements = value;
-      fieldSetFlags()[5] = true;
+      fieldSetFlags()[6] = true;
       return this; 
     }
     
     /** Checks whether the 'agreements' field has been set */
     public boolean hasAgreements() {
-      return fieldSetFlags()[5];
+      return fieldSetFlags()[6];
     }
     
     /** Clears the value of the 'agreements' field */
     public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg.Builder clearAgreements() {
       agreements = null;
-      fieldSetFlags()[5] = false;
+      fieldSetFlags()[6] = false;
       return this;
     }
 
@@ -354,7 +401,8 @@ public class UserAgreementHistoryMsg extends org.apache.avro.specific.SpecificRe
         record.userID = fieldSetFlags()[2] ? this.userID : (java.lang.String) defaultValue(fields()[2]);
         record.latestOccurredMillis = fieldSetFlags()[3] ? this.latestOccurredMillis : (java.lang.Long) defaultValue(fields()[3]);
         record.latestValidFromMillis = fieldSetFlags()[4] ? this.latestValidFromMillis : (java.lang.Long) defaultValue(fields()[4]);
-        record.agreements = fieldSetFlags()[5] ? this.agreements : (java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg>) defaultValue(fields()[5]);
+        record.userCreationTimeMillis = fieldSetFlags()[5] ? this.userCreationTimeMillis : (java.lang.Long) defaultValue(fields()[5]);
+        record.agreements = fieldSetFlags()[6] ? this.agreements : (java.util.List<gr.grnet.aquarium.message.avro.gen.UserAgreementMsg>) defaultValue(fields()[6]);
         return record;
       } catch (Exception e) {
         throw new org.apache.avro.AvroRuntimeException(e);
index 705ec11..dd0e661 100644 (file)
@@ -6,17 +6,15 @@
 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\":\"resourceTypesMap\",\"type\":{\"type\":\"map\",\"values\":{\"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\"}}]},\"avro.java.string\":\"String\"}},{\"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\":\"double\"},{\"name\":\"oldAccumulatingAmount\",\"type\":\"double\"},{\"name\":\"previousValue\",\"type\":\"double\"},{\"name\":\"currentValue\",\"type\":\"double\"}]},\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":\"double\",\"default\":0.0},{\"name\":\"agreementHistory\",\"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\":\"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\":\"double\"},{\"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\":\"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\":\"double\"},{\"name\":\"oldTotalCredits\",\"type\":\"double\"},{\"name\":\"newTotalCredits\",\"type\":\"double\"},{\"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\":\"double\"},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":\"double\",\"default\":0.0}]}}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":\"ResourceTypeMsg\"},{\"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\":\"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\":\"double\"},{\"name\":\"oldAccumulatingAmount\",\"type\":\"double\"},{\"name\":\"previousValue\",\"type\":\"double\"},{\"name\":\"currentValue\",\"type\":\"double\"}]},\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":\"double\",\"default\":0.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\":\"double\"},{\"name\":\"oldTotalCredits\",\"type\":\"double\"},{\"name\":\"newTotalCredits\",\"type\":\"double\"},{\"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\":\"double\"},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":\"double\",\"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}]}}}]}");
   @Deprecated public java.lang.String originalID;
   @Deprecated public java.lang.String inStoreID;
   @Deprecated public java.lang.String userID;
   @Deprecated public long occurredMillis;
   @Deprecated public java.lang.String parentOriginalID;
   @Deprecated public java.lang.String parentInStoreID;
-  @Deprecated public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> resourceTypesMap;
   @Deprecated public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> stateOfResources;
   @Deprecated public double totalCredits;
-  @Deprecated public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg agreementHistory;
   @Deprecated public long latestUpdateMillis;
   @Deprecated public long latestResourceEventOccurredMillis;
   @Deprecated public long billingPeriodOutOfSyncResourceEventsCounter;
@@ -35,18 +33,16 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     case 3: return occurredMillis;
     case 4: return parentOriginalID;
     case 5: return parentInStoreID;
-    case 6: return resourceTypesMap;
-    case 7: return stateOfResources;
-    case 8: return totalCredits;
-    case 9: return agreementHistory;
-    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 isFullBillingMonth;
-    case 17: return walletEntries;
+    case 6: return stateOfResources;
+    case 7: return totalCredits;
+    case 8: return latestUpdateMillis;
+    case 9: return latestResourceEventOccurredMillis;
+    case 10: return billingPeriodOutOfSyncResourceEventsCounter;
+    case 11: return billingYear;
+    case 12: return billingMonth;
+    case 13: return billingMonthDay;
+    case 14: return isFullBillingMonth;
+    case 15: return walletEntries;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -60,18 +56,16 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     case 3: occurredMillis = (java.lang.Long)value$; break;
     case 4: parentOriginalID = (java.lang.String)value$; break;
     case 5: parentInStoreID = (java.lang.String)value$; break;
-    case 6: resourceTypesMap = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>)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.Double)value$; break;
-    case 9: agreementHistory = (gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg)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: isFullBillingMonth = (java.lang.Boolean)value$; break;
-    case 17: walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>)value$; break;
+    case 6: stateOfResources = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>)value$; break;
+    case 7: totalCredits = (java.lang.Double)value$; break;
+    case 8: latestUpdateMillis = (java.lang.Long)value$; break;
+    case 9: latestResourceEventOccurredMillis = (java.lang.Long)value$; break;
+    case 10: billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long)value$; break;
+    case 11: billingYear = (java.lang.Integer)value$; break;
+    case 12: billingMonth = (java.lang.Integer)value$; break;
+    case 13: billingMonthDay = (java.lang.Integer)value$; break;
+    case 14: isFullBillingMonth = (java.lang.Boolean)value$; break;
+    case 15: walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>)value$; break;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
   }
@@ -167,21 +161,6 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   }
 
   /**
-   * Gets the value of the 'resourceTypesMap' field.
-   */
-  public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> getResourceTypesMap() {
-    return resourceTypesMap;
-  }
-
-  /**
-   * Sets the value of the 'resourceTypesMap' field.
-   * @param value the value to set.
-   */
-  public void setResourceTypesMap(java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> value) {
-    this.resourceTypesMap = value;
-  }
-
-  /**
    * Gets the value of the 'stateOfResources' field.
    */
   public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> getStateOfResources() {
@@ -212,21 +191,6 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
   }
 
   /**
-   * Gets the value of the 'agreementHistory' field.
-   */
-  public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg getAgreementHistory() {
-    return agreementHistory;
-  }
-
-  /**
-   * Sets the value of the 'agreementHistory' field.
-   * @param value the value to set.
-   */
-  public void setAgreementHistory(gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg value) {
-    this.agreementHistory = value;
-  }
-
-  /**
    * Gets the value of the 'latestUpdateMillis' field.
    */
   public java.lang.Long getLatestUpdateMillis() {
@@ -373,10 +337,8 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     private long occurredMillis;
     private java.lang.String parentOriginalID;
     private java.lang.String parentInStoreID;
-    private java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> resourceTypesMap;
     private java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg> stateOfResources;
     private double totalCredits;
-    private gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg agreementHistory;
     private long latestUpdateMillis;
     private long latestResourceEventOccurredMillis;
     private long billingPeriodOutOfSyncResourceEventsCounter;
@@ -423,54 +385,46 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
         this.parentInStoreID = (java.lang.String) data().deepCopy(fields()[5].schema(), other.parentInStoreID);
         fieldSetFlags()[5] = true;
       }
-      if (isValidValue(fields()[6], other.resourceTypesMap)) {
-        this.resourceTypesMap = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>) data().deepCopy(fields()[6].schema(), other.resourceTypesMap);
+      if (isValidValue(fields()[6], other.stateOfResources)) {
+        this.stateOfResources = (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>) data().deepCopy(fields()[6].schema(), other.stateOfResources);
         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.totalCredits)) {
+        this.totalCredits = (java.lang.Double) data().deepCopy(fields()[7].schema(), other.totalCredits);
         fieldSetFlags()[7] = true;
       }
-      if (isValidValue(fields()[8], other.totalCredits)) {
-        this.totalCredits = (java.lang.Double) data().deepCopy(fields()[8].schema(), other.totalCredits);
+      if (isValidValue(fields()[8], other.latestUpdateMillis)) {
+        this.latestUpdateMillis = (java.lang.Long) data().deepCopy(fields()[8].schema(), other.latestUpdateMillis);
         fieldSetFlags()[8] = true;
       }
-      if (isValidValue(fields()[9], other.agreementHistory)) {
-        this.agreementHistory = (gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg) data().deepCopy(fields()[9].schema(), other.agreementHistory);
+      if (isValidValue(fields()[9], other.latestResourceEventOccurredMillis)) {
+        this.latestResourceEventOccurredMillis = (java.lang.Long) data().deepCopy(fields()[9].schema(), other.latestResourceEventOccurredMillis);
         fieldSetFlags()[9] = true;
       }
-      if (isValidValue(fields()[10], other.latestUpdateMillis)) {
-        this.latestUpdateMillis = (java.lang.Long) data().deepCopy(fields()[10].schema(), other.latestUpdateMillis);
+      if (isValidValue(fields()[10], other.billingPeriodOutOfSyncResourceEventsCounter)) {
+        this.billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long) data().deepCopy(fields()[10].schema(), other.billingPeriodOutOfSyncResourceEventsCounter);
         fieldSetFlags()[10] = true;
       }
-      if (isValidValue(fields()[11], other.latestResourceEventOccurredMillis)) {
-        this.latestResourceEventOccurredMillis = (java.lang.Long) data().deepCopy(fields()[11].schema(), other.latestResourceEventOccurredMillis);
+      if (isValidValue(fields()[11], other.billingYear)) {
+        this.billingYear = (java.lang.Integer) data().deepCopy(fields()[11].schema(), other.billingYear);
         fieldSetFlags()[11] = true;
       }
-      if (isValidValue(fields()[12], other.billingPeriodOutOfSyncResourceEventsCounter)) {
-        this.billingPeriodOutOfSyncResourceEventsCounter = (java.lang.Long) data().deepCopy(fields()[12].schema(), other.billingPeriodOutOfSyncResourceEventsCounter);
+      if (isValidValue(fields()[12], other.billingMonth)) {
+        this.billingMonth = (java.lang.Integer) data().deepCopy(fields()[12].schema(), other.billingMonth);
         fieldSetFlags()[12] = true;
       }
-      if (isValidValue(fields()[13], other.billingYear)) {
-        this.billingYear = (java.lang.Integer) data().deepCopy(fields()[13].schema(), other.billingYear);
+      if (isValidValue(fields()[13], other.billingMonthDay)) {
+        this.billingMonthDay = (java.lang.Integer) data().deepCopy(fields()[13].schema(), other.billingMonthDay);
         fieldSetFlags()[13] = true;
       }
-      if (isValidValue(fields()[14], other.billingMonth)) {
-        this.billingMonth = (java.lang.Integer) data().deepCopy(fields()[14].schema(), other.billingMonth);
+      if (isValidValue(fields()[14], other.isFullBillingMonth)) {
+        this.isFullBillingMonth = (java.lang.Boolean) data().deepCopy(fields()[14].schema(), other.isFullBillingMonth);
         fieldSetFlags()[14] = true;
       }
-      if (isValidValue(fields()[15], other.billingMonthDay)) {
-        this.billingMonthDay = (java.lang.Integer) data().deepCopy(fields()[15].schema(), other.billingMonthDay);
+      if (isValidValue(fields()[15], other.walletEntries)) {
+        this.walletEntries = (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) data().deepCopy(fields()[15].schema(), other.walletEntries);
         fieldSetFlags()[15] = true;
       }
-      if (isValidValue(fields()[16], other.isFullBillingMonth)) {
-        this.isFullBillingMonth = (java.lang.Boolean) data().deepCopy(fields()[16].schema(), other.isFullBillingMonth);
-        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 */
@@ -622,31 +576,6 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
       return this;
     }
 
-    /** Gets the value of the 'resourceTypesMap' field */
-    public java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> getResourceTypesMap() {
-      return resourceTypesMap;
-    }
-    
-    /** Sets the value of the 'resourceTypesMap' field */
-    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setResourceTypesMap(java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg> value) {
-      validate(fields()[6], value);
-      this.resourceTypesMap = value;
-      fieldSetFlags()[6] = true;
-      return this; 
-    }
-    
-    /** Checks whether the 'resourceTypesMap' field has been set */
-    public boolean hasResourceTypesMap() {
-      return fieldSetFlags()[6];
-    }
-    
-    /** Clears the value of the 'resourceTypesMap' field */
-    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearResourceTypesMap() {
-      resourceTypesMap = null;
-      fieldSetFlags()[6] = 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;
@@ -654,21 +583,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()[6], value);
       this.stateOfResources = value;
-      fieldSetFlags()[7] = true;
+      fieldSetFlags()[6] = true;
       return this; 
     }
     
     /** Checks whether the 'stateOfResources' field has been set */
     public boolean hasStateOfResources() {
-      return fieldSetFlags()[7];
+      return fieldSetFlags()[6];
     }
     
     /** Clears the value of the 'stateOfResources' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearStateOfResources() {
       stateOfResources = null;
-      fieldSetFlags()[7] = false;
+      fieldSetFlags()[6] = false;
       return this;
     }
 
@@ -679,45 +608,20 @@ 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(double value) {
-      validate(fields()[8], value);
+      validate(fields()[7], value);
       this.totalCredits = value;
-      fieldSetFlags()[8] = true;
+      fieldSetFlags()[7] = true;
       return this; 
     }
     
     /** Checks whether the 'totalCredits' field has been set */
     public boolean hasTotalCredits() {
-      return fieldSetFlags()[8];
+      return fieldSetFlags()[7];
     }
     
     /** Clears the value of the 'totalCredits' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearTotalCredits() {
-      fieldSetFlags()[8] = false;
-      return this;
-    }
-
-    /** Gets the value of the 'agreementHistory' field */
-    public gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg getAgreementHistory() {
-      return agreementHistory;
-    }
-    
-    /** Sets the value of the 'agreementHistory' field */
-    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setAgreementHistory(gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg value) {
-      validate(fields()[9], value);
-      this.agreementHistory = value;
-      fieldSetFlags()[9] = true;
-      return this; 
-    }
-    
-    /** Checks whether the 'agreementHistory' field has been set */
-    public boolean hasAgreementHistory() {
-      return fieldSetFlags()[9];
-    }
-    
-    /** Clears the value of the 'agreementHistory' field */
-    public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearAgreementHistory() {
-      agreementHistory = null;
-      fieldSetFlags()[9] = false;
+      fieldSetFlags()[7] = false;
       return this;
     }
 
@@ -728,20 +632,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()[10], value);
+      validate(fields()[8], value);
       this.latestUpdateMillis = value;
-      fieldSetFlags()[10] = true;
+      fieldSetFlags()[8] = true;
       return this; 
     }
     
     /** Checks whether the 'latestUpdateMillis' field has been set */
     public boolean hasLatestUpdateMillis() {
-      return fieldSetFlags()[10];
+      return fieldSetFlags()[8];
     }
     
     /** Clears the value of the 'latestUpdateMillis' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearLatestUpdateMillis() {
-      fieldSetFlags()[10] = false;
+      fieldSetFlags()[8] = false;
       return this;
     }
 
@@ -752,20 +656,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()[11], value);
+      validate(fields()[9], value);
       this.latestResourceEventOccurredMillis = value;
-      fieldSetFlags()[11] = true;
+      fieldSetFlags()[9] = true;
       return this; 
     }
     
     /** Checks whether the 'latestResourceEventOccurredMillis' field has been set */
     public boolean hasLatestResourceEventOccurredMillis() {
-      return fieldSetFlags()[11];
+      return fieldSetFlags()[9];
     }
     
     /** Clears the value of the 'latestResourceEventOccurredMillis' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearLatestResourceEventOccurredMillis() {
-      fieldSetFlags()[11] = false;
+      fieldSetFlags()[9] = false;
       return this;
     }
 
@@ -776,20 +680,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()[12], value);
+      validate(fields()[10], value);
       this.billingPeriodOutOfSyncResourceEventsCounter = value;
-      fieldSetFlags()[12] = true;
+      fieldSetFlags()[10] = true;
       return this; 
     }
     
     /** Checks whether the 'billingPeriodOutOfSyncResourceEventsCounter' field has been set */
     public boolean hasBillingPeriodOutOfSyncResourceEventsCounter() {
-      return fieldSetFlags()[12];
+      return fieldSetFlags()[10];
     }
     
     /** Clears the value of the 'billingPeriodOutOfSyncResourceEventsCounter' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingPeriodOutOfSyncResourceEventsCounter() {
-      fieldSetFlags()[12] = false;
+      fieldSetFlags()[10] = false;
       return this;
     }
 
@@ -800,20 +704,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()[13], value);
+      validate(fields()[11], value);
       this.billingYear = value;
-      fieldSetFlags()[13] = true;
+      fieldSetFlags()[11] = true;
       return this; 
     }
     
     /** Checks whether the 'billingYear' field has been set */
     public boolean hasBillingYear() {
-      return fieldSetFlags()[13];
+      return fieldSetFlags()[11];
     }
     
     /** Clears the value of the 'billingYear' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingYear() {
-      fieldSetFlags()[13] = false;
+      fieldSetFlags()[11] = false;
       return this;
     }
 
@@ -824,20 +728,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()[14], value);
+      validate(fields()[12], value);
       this.billingMonth = value;
-      fieldSetFlags()[14] = true;
+      fieldSetFlags()[12] = true;
       return this; 
     }
     
     /** Checks whether the 'billingMonth' field has been set */
     public boolean hasBillingMonth() {
-      return fieldSetFlags()[14];
+      return fieldSetFlags()[12];
     }
     
     /** Clears the value of the 'billingMonth' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingMonth() {
-      fieldSetFlags()[14] = false;
+      fieldSetFlags()[12] = false;
       return this;
     }
 
@@ -848,20 +752,20 @@ 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()[15], value);
+      validate(fields()[13], value);
       this.billingMonthDay = value;
-      fieldSetFlags()[15] = true;
+      fieldSetFlags()[13] = true;
       return this; 
     }
     
     /** Checks whether the 'billingMonthDay' field has been set */
     public boolean hasBillingMonthDay() {
-      return fieldSetFlags()[15];
+      return fieldSetFlags()[13];
     }
     
     /** Clears the value of the 'billingMonthDay' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearBillingMonthDay() {
-      fieldSetFlags()[15] = false;
+      fieldSetFlags()[13] = false;
       return this;
     }
 
@@ -872,20 +776,20 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
     
     /** Sets the value of the 'isFullBillingMonth' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder setIsFullBillingMonth(boolean value) {
-      validate(fields()[16], value);
+      validate(fields()[14], value);
       this.isFullBillingMonth = value;
-      fieldSetFlags()[16] = true;
+      fieldSetFlags()[14] = true;
       return this; 
     }
     
     /** Checks whether the 'isFullBillingMonth' field has been set */
     public boolean hasIsFullBillingMonth() {
-      return fieldSetFlags()[16];
+      return fieldSetFlags()[14];
     }
     
     /** Clears the value of the 'isFullBillingMonth' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearIsFullBillingMonth() {
-      fieldSetFlags()[16] = false;
+      fieldSetFlags()[14] = false;
       return this;
     }
 
@@ -896,21 +800,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()[17], value);
+      validate(fields()[15], value);
       this.walletEntries = value;
-      fieldSetFlags()[17] = true;
+      fieldSetFlags()[15] = true;
       return this; 
     }
     
     /** Checks whether the 'walletEntries' field has been set */
     public boolean hasWalletEntries() {
-      return fieldSetFlags()[17];
+      return fieldSetFlags()[15];
     }
     
     /** Clears the value of the 'walletEntries' field */
     public gr.grnet.aquarium.message.avro.gen.UserStateMsg.Builder clearWalletEntries() {
       walletEntries = null;
-      fieldSetFlags()[17] = false;
+      fieldSetFlags()[15] = false;
       return this;
     }
 
@@ -924,18 +828,16 @@ public class UserStateMsg extends org.apache.avro.specific.SpecificRecordBase im
         record.occurredMillis = fieldSetFlags()[3] ? this.occurredMillis : (java.lang.Long) defaultValue(fields()[3]);
         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.resourceTypesMap = fieldSetFlags()[6] ? this.resourceTypesMap : (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourceTypeMsg>) 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.Double) defaultValue(fields()[8]);
-        record.agreementHistory = fieldSetFlags()[9] ? this.agreementHistory : (gr.grnet.aquarium.message.avro.gen.UserAgreementHistoryMsg) 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.isFullBillingMonth = fieldSetFlags()[16] ? this.isFullBillingMonth : (java.lang.Boolean) defaultValue(fields()[16]);
-        record.walletEntries = fieldSetFlags()[17] ? this.walletEntries : (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) defaultValue(fields()[17]);
+        record.stateOfResources = fieldSetFlags()[6] ? this.stateOfResources : (java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.ResourcesChargingStateMsg>) defaultValue(fields()[6]);
+        record.totalCredits = fieldSetFlags()[7] ? this.totalCredits : (java.lang.Double) defaultValue(fields()[7]);
+        record.latestUpdateMillis = fieldSetFlags()[8] ? this.latestUpdateMillis : (java.lang.Long) defaultValue(fields()[8]);
+        record.latestResourceEventOccurredMillis = fieldSetFlags()[9] ? this.latestResourceEventOccurredMillis : (java.lang.Long) defaultValue(fields()[9]);
+        record.billingPeriodOutOfSyncResourceEventsCounter = fieldSetFlags()[10] ? this.billingPeriodOutOfSyncResourceEventsCounter : (java.lang.Long) defaultValue(fields()[10]);
+        record.billingYear = fieldSetFlags()[11] ? this.billingYear : (java.lang.Integer) defaultValue(fields()[11]);
+        record.billingMonth = fieldSetFlags()[12] ? this.billingMonth : (java.lang.Integer) defaultValue(fields()[12]);
+        record.billingMonthDay = fieldSetFlags()[13] ? this.billingMonthDay : (java.lang.Integer) defaultValue(fields()[13]);
+        record.isFullBillingMonth = fieldSetFlags()[14] ? this.isFullBillingMonth : (java.lang.Boolean) defaultValue(fields()[14]);
+        record.walletEntries = fieldSetFlags()[15] ? this.walletEntries : (java.util.List<gr.grnet.aquarium.message.avro.gen.WalletEntryMsg>) defaultValue(fields()[15]);
         return record;
       } catch (Exception e) {
         throw new org.apache.avro.AvroRuntimeException(e);
index 2e98232..7c404d4 100644 (file)
@@ -56,6 +56,7 @@ import java.util.concurrent.atomic.AtomicBoolean
 import org.slf4j.{LoggerFactory, Logger}
 import gr.grnet.aquarium.event.CreditsModel
 import gr.grnet.aquarium.charging.state.UserStateBootstrap
+import java.util.{Map ⇒ JMap}
 
 /**
  *
@@ -232,17 +233,37 @@ final class Aquarium(env: Env) extends Lifecycle with Loggable {
 
   }
 
-  def currentResourceTypesMap: Map[String, ResourceType] = {
-    val policyMspOpt = policyStore.loadPolicyAt(TimeHelpers.nowMillis())
+  def resourceMappingAtMillis(millis: Long): JMap[String, ResourceTypeMsg] = {
+    val policyMspOpt = policyStore.loadPolicyAt(millis)
     if(policyMspOpt.isEmpty) {
-      throw new AquariumInternalError("Not even the default policy found")
+      throw new AquariumInternalError(
+        "Cannot get resource mapping. Not even the default policy found for time %s",
+        TimeHelpers.toYYYYMMDDHHMMSSSSS(millis)
+      )
     }
 
     val policyMsg = policyMspOpt.get
-    // TODO optimize
-    ModelFactory.newPolicyModel(policyMsg).resourceTypesMap
+    policyMsg.getResourceMapping
   }
 
+//  def resourceTypesMapAtMillis(millis: Long): Map[String, ResourceType] = {
+//    val policyMspOpt = policyStore.loadPolicyAt(millis)
+//    if(policyMspOpt.isEmpty) {
+//      throw new AquariumInternalError(
+//        "Cannot get resource types map. Not even the default policy found for time %s",
+//        TimeHelpers.toYYYYMMDDHHMMSSSSS(millis)
+//      )
+//    }
+//
+//    val policyMsg = policyMspOpt.get
+//    // TODO optimize
+//    ModelFactory.newPolicyModel(policyMsg).resourceTypesMap
+//  }
+//
+//  def currentResourceTypesMap: Map[String, ResourceType] = {
+//    resourceTypesMapAtMillis(TimeHelpers.nowMillis())
+//  }
+
   def unsafeValidPolicyModelAt(referenceTimeMillis: Long): PolicyModel = {
     policyStore.loadPolicyAt(referenceTimeMillis) match {
       case None ⇒
index eeb4821..f1feaeb 100644 (file)
@@ -52,13 +52,15 @@ 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.computation.BillingMonthInfo
-import gr.grnet.aquarium.message.avro.gen.{IMEventMsg, ResourceEventMsg, UserStateMsg}
+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.service.event.BalanceEvent
 import gr.grnet.aquarium.util.date.TimeHelpers
 import gr.grnet.aquarium.util.{LogHelpers, shortClassNameOf}
 import gr.grnet.aquarium.policy.{ResourceType, PolicyModel}
 import gr.grnet.aquarium.charging.bill.BillEntryMsg
+import gr.grnet.aquarium.event.CreditsModel
+import java.util
 
 /**
  *
@@ -68,14 +70,9 @@ import gr.grnet.aquarium.charging.bill.BillEntryMsg
 class UserActor extends ReflectiveRoleableActor {
   private[this] var _rcMsgCount = 0
   private[this] var _imMsgCount = 0
-  private[this] var _userID: String = "<?>"
-  private[this] var _userState: UserStateModel = _
-  private[this] var _userCreationIMEvent: IMEventMsg = _
+  private[this] var _userID: String = "???"
+  private[this] var _userStateMsg: UserStateMsg = _
   private[this] var _userAgreementHistoryModel: UserAgreementHistoryModel = _
-  private[this] var _latestIMEventOriginalID: String = ""
-  private[this] var _latestIMEventOccurredMillis: Long = -1L
-  private[this] var _latestResourceEventOriginalID: String = ""
-  private[this] var _userStateBootstrap: UserStateBootstrap = _
 
   def unsafeUserID = {
     if(!haveUserID) {
@@ -111,94 +108,46 @@ class UserActor extends ReflectiveRoleableActor {
     aquarium.userStateStore.insertUserState(userState)
   }
 
-  @inline private[this] def haveUserID = {
-    this._userID ne null
-  }
-
   def onAquariumPropertiesLoaded(event: AquariumPropertiesLoaded): Unit = {
   }
 
-  @inline private[this] def haveAgreements = {
-    (this._userAgreementHistoryModel ne null) && this._userAgreementHistoryModel.size > 0
-  }
+  private[this] def haveUserID = this._userID ne null
+  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
 
-  @inline private[this] def haveUserState = {
-    this._userState ne null
-  }
+  private[this] def createInitialUserStateMsgFromCreateIMEvent() {
+    assert(haveAgreements, "haveAgreements")
+    assert(isUserCreated, "isUserCreated")
+    assert(this._userAgreementHistoryModel.hasUserCreationEvent, "this._userAgreementHistoryModel.hasUserCreationEvent")
 
-  @inline private[this] def haveUserStateBootstrap = {
-    this._userStateBootstrap ne null
-  }
-
-  private[this] def createUserAgreementHistoryModel(imEvent: IMEventMsg) {
-    assert(MessageHelpers.isIMEventCreate(imEvent))
-    assert(this._userAgreementHistoryModel eq null)
-    assert(this._userCreationIMEvent eq null)
+    val userCreationIMEventMsg = unsafeUserCreationIMEventMsg
+    val userStateBootstrap = aquarium.getUserStateBootstrap(userCreationIMEventMsg)
 
-    this._userCreationIMEvent = imEvent
-    this._userAgreementHistoryModel = ModelFactory.newUserAgreementHistoryModelFromIMEvent(
-      imEvent,
-      imEvent.getOriginalID
+    this._userStateMsg = MessageFactory.newInitialUserStateMsg(
+      this._userID,
+      CreditsModel.from(0.0),
+      TimeHelpers.nowMillis()
     )
   }
 
-  private[this] def updateAgreementHistoryFrom(imEvent: IMEventMsg): Unit = {
-    val isCreateUser = MessageHelpers.isIMEventCreate(imEvent)
-    if(isCreateUser) {
-      if(haveAgreements) {
-        throw new AquariumInternalError(
-          "Got user creation event (id=%s) but I already have one (id=%s)",
-          this._userCreationIMEvent.getOriginalID,
-          imEvent.getOriginalID
-        )
-      }
-
-      createUserAgreementHistoryModel(imEvent) // now we have an agreement history
-      createUserStateBootstrap(imEvent)
-    }
-
-    val effectiveFromMillis = imEvent.getOccurredMillis
-    val role = imEvent.getRole
-    // calling unsafe just for the side-effect
-    assert(null ne aquarium.unsafeFullPriceTableForRoleAt(role, effectiveFromMillis))
-
-    // add to model (will update the underlying messages as well)
-    val newUserAgreementModel = ModelFactory.newUserAgreementModelFromIMEvent(imEvent, imEvent.getOriginalID)
-    this._userAgreementHistoryModel += newUserAgreementModel
-
-    // We assume that we always call this method with in-sync events
-    assert(imEvent.getOccurredMillis >= this._latestIMEventOccurredMillis)
-    updateLatestIMEventStateFrom(imEvent)
-  }
-
-//  private[this] def updateLatestIMEventIDFrom(imEvent: IMEventMsg): Unit = {
-//    this._latestIMEventOriginalID = imEvent.getOriginalID
-//  }
-
-  private[this] def updateLatestIMEventStateFrom(imEvent: IMEventMsg) {
-    this._latestIMEventOriginalID = imEvent.getOriginalID
-    this._latestIMEventOccurredMillis = imEvent.getOccurredMillis
-    this._imMsgCount += 1
-  }
-
-  private[this] def updateLatestResourceEventIDFrom(rcEvent: ResourceEventMsg): Unit = {
-    this._latestResourceEventOriginalID = rcEvent.getOriginalID
-  }
-
   /**
-   * Creates the initial state that is related to IMEvents.
+   * Creates the agreement history from all the stored IMEvents.
    *
-   * @return `true` if there was a user CREATE event
+   * @return (`true` iff there was a user CREATE event, the number of events processed)
    */
-  private[this] def initializeStateOfIMEvents(): Boolean = {
-    DEBUG("initializeStateOfIMEvents()")
+  private[this] def createUserAgreementHistoryFromStoredIMEvents(): (Boolean, Int) = {
+    DEBUG("createUserAgreementHistoryFromStoredIMEvents()")
+    val historyMsg = MessageFactory.newUserAgreementHistoryMsg(this._userID)
+    this._userAgreementHistoryModel = ModelFactory.newUserAgreementHistoryModel(historyMsg)
 
     // NOTE: this._userID is already set up our caller
     var _imcounter = 0
 
-    aquarium.imEventStore.foreachIMEventInOccurrenceOrder(this._userID) { imEvent ⇒
+    val hadCreateEvent = aquarium.imEventStore.foreachIMEventInOccurrenceOrder(this._userID) { imEvent ⇒
       _imcounter += 1
-      DEBUG("Replaying [%s] %s", _imcounter, imEvent)
+      DEBUG("Replaying [%s/%s] %s", shortClassNameOf(imEvent), _imcounter, imEvent)
 
       if(_imcounter == 1 && !MessageHelpers.isIMEventCreate(imEvent)) {
         // The very first event must be a CREATE event. Otherwise we abort initialization.
@@ -207,71 +156,21 @@ class UserActor extends ReflectiveRoleableActor {
         false
       }
       else {
-        updateAgreementHistoryFrom(imEvent)
+        val effectiveFromMillis = imEvent.getOccurredMillis
+        val role = imEvent.getRole
+        // calling unsafe just for the side-effect
+        assert(
+          aquarium.unsafeFullPriceTableForRoleAt(role, effectiveFromMillis) ne null,
+          "aquarium.unsafeFullPriceTableForRoleAt(%s, %s) ne null".format(role, effectiveFromMillis)
+        )
+
+        this._userAgreementHistoryModel.insertUserAgreementMsgFromIMEvent(imEvent)
         true
       }
     }
-  }
-
-  private[this] def loadUserStateAndUpdateAgreementHistory(): Unit = {
-    assert(this.haveAgreements, "this.haveAgreements")
-
-    if(!haveUserStateBootstrap) {
-      this._userStateBootstrap = aquarium.getUserStateBootstrap(this._userCreationIMEvent)
-    }
-    logger.debug("#### this._userStateBootStrap %s".format(this._userStateBootstrap.toString))
-    val now = TimeHelpers.nowMillis()
-    this._userState = chargingService.replayMonthChargingUpTo(
-      BillingMonthInfo.fromMillis(now),
-      now,
-      this._userStateBootstrap,
-      aquarium.currentResourceTypesMap,
-      aquarium.userStateStore.insertUserState
-    )
-
-    // Final touch: Update agreement history in the working user state.
-    // The assumption is that all agreement changes go via IMEvents, so the
-    // state this._workingAgreementHistory is always the authoritative source.
-    if(haveUserState) {
-      this._userState.userAgreementHistoryModel = this._userAgreementHistoryModel
-      DEBUG("Computed working user state %s", AvroHelpers.jsonStringOfSpecificRecord(this._userState.msg))
-    }
-  }
-
-  private[this] def initializeStateOfResourceEvents(): Unit = {
-    DEBUG("initializeStateOfResourceEvents()")
-    assert(haveAgreements)
-
-    // We will also need this functionality when receiving IMEvents, so we place it in a method
-    loadUserStateAndUpdateAgreementHistory()
 
-    if(haveUserState) {
-      DEBUG("Initial working user state %s", AvroHelpers.jsonStringOfSpecificRecord(this._userState.msg))
-      logSeparator()
-    }
-  }
-
-  /**
-   * Initializes the actor state from DB.
-   */
-  def initializeUserActorState(userID: String): Boolean = {
-    this._userID = userID
-
-    if(initializeStateOfIMEvents()) {
-      initializeStateOfResourceEvents()
-      // Even if we have no resource events, the user is at least CREATEd
-      true
-    }
-    else {
-      false
-    }
-  }
-
-  def createUserStateBootstrap(imEvent: IMEventMsg) {
-    assert(MessageHelpers.isIMEventCreate(imEvent), "MessageHelpers.isIMEventCreate(imEvent)")
-    assert(this._userCreationIMEvent == imEvent, "this._userCreationIMEvent == imEvent")
-
-    this._userStateBootstrap = aquarium.getUserStateBootstrap(this._userCreationIMEvent)
+    DEBUG("Agreements: %s", this._userAgreementHistoryModel)
+    (hadCreateEvent, _imcounter)
   }
 
   /**
@@ -279,16 +178,17 @@ class UserActor extends ReflectiveRoleableActor {
    * messaging hub (rabbitmq).
    */
   def onIMEventMsg(imEvent: IMEventMsg) {
-    if(!haveAgreements) {
-      // If we have no agreements so far, then it does not matter what kind of event
-      // this is. So we replay the log (ehm.. store)
-      initializeUserActorState(imEvent.getUserID)
+    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._latestIMEventOccurredMillis
+    val isOutOfSyncIM = imEvent.getOccurredMillis < this._userAgreementHistoryModel.latestIMEventOccurredMillis
     if(isOutOfSyncIM) {
       // clear all resource state
       // FIXME implement
@@ -306,21 +206,22 @@ class UserActor extends ReflectiveRoleableActor {
 
     // OK, seems good
     assert(!MessageHelpers.isIMEventCreate(imEvent), "!MessageHelpers.isIMEventCreate(imEvent)")
-    updateAgreementHistoryFrom(imEvent)
+
+    // Make new agreement
+    this._userAgreementHistoryModel.insertUserAgreementMsgFromIMEvent(imEvent)
+    this._imMsgCount += 1
+    DEBUG("Agreements: %s", this._userAgreementHistoryModel)
   }
 
   def onResourceEventMsg(rcEvent: ResourceEventMsg) {
-    if(!haveAgreements) {
-      DEBUG("No agreement. Ignoring %s", rcEvent)
+    if(!isUserCreated) {
+      DEBUG("No agreements. Ignoring %s", rcEvent)
 
       return
     }
 
     val now = TimeHelpers.nowMillis()
-    // TODO: Review this and its usage in user state.
-    // TODO: The assumption is that the resource set increases all the time,
-    // TODO: so the current map contains everything ever known (assuming we do not run backwards in time).
-    val currentResourcesMap = aquarium.currentResourceTypesMap
+    val resourceMapping = aquarium.resourceMappingAtMillis(now)
 
     val nowBillingMonthInfo = BillingMonthInfo.fromMillis(now)
     val nowYear = nowBillingMonthInfo.year
@@ -333,38 +234,40 @@ class UserActor extends ReflectiveRoleableActor {
 
     def computeBatch(): Unit = {
       DEBUG("Going for out of sync charging for %s", rcEvent.getOriginalID)
-      this._userState = chargingService.replayMonthChargingUpTo(
+
+      this._userStateMsg = chargingService.replayMonthChargingUpTo(
+        this._userAgreementHistoryModel,
         nowBillingMonthInfo,
         // Take into account that the event may be out-of-sync.
         // TODO: Should we use this._latestResourceEventOccurredMillis instead of now?
         now max eventOccurredMillis,
-        this._userStateBootstrap,
-        currentResourcesMap,
+        resourceMapping,
         stdUserStateStoreFunc
       )
 
-      updateLatestResourceEventIDFrom(rcEvent)
     }
 
     def computeRealtime(): Unit = {
       DEBUG("Going for in sync charging for %s", rcEvent.getOriginalID)
       chargingService.processResourceEvent(
         rcEvent,
-        this._userState,
+        this._userAgreementHistoryModel,
+        this._userStateMsg,
         nowBillingMonthInfo,
-        true
+        true,
+        resourceMapping
       )
 
-      updateLatestResourceEventIDFrom(rcEvent)
+      this._rcMsgCount += 1
     }
 
     val oldTotalCredits =
-      if(this._userState!=null)
-        this._userState.totalCredits
+      if(this._userStateMsg!=null)
+        this._userStateMsg.totalCredits
       else
         0.0D
     // FIXME check these
-    if(this._userState eq null) {
+    if(this._userStateMsg eq null) {
       computeBatch()
     }
     else if(nowYear != eventYear || nowMonth != eventMonth) {
@@ -375,41 +278,41 @@ class UserActor extends ReflectiveRoleableActor {
       )
       computeBatch()
     }
-    else if(this._userState.latestResourceEventOccurredMillis < rcEvent.getOccurredMillis) {
+    else if(this._userStateMsg.latestResourceEventOccurredMillis < rcEvent.getOccurredMillis) {
       DEBUG("this._workingUserState.latestResourceEventOccurredMillis < rcEvent.occurredMillis")
       DEBUG(
         "%s < %s",
-        TimeHelpers.toYYYYMMDDHHMMSSSSS(this._userState.latestResourceEventOccurredMillis),
+        TimeHelpers.toYYYYMMDDHHMMSSSSS(this._userStateMsg.latestResourceEventOccurredMillis),
         TimeHelpers.toYYYYMMDDHHMMSSSSS(rcEvent.getOccurredMillis)
       )
       computeRealtime()
     }
     else {
       DEBUG("OUT OF ORDER! this._workingUserState.latestResourceEventOccurredMillis=%s  and rcEvent.occurredMillis=%s",
-        TimeHelpers.toYYYYMMDDHHMMSSSSS(this._userState.latestResourceEventOccurredMillis),
+        TimeHelpers.toYYYYMMDDHHMMSSSSS(this._userStateMsg.latestResourceEventOccurredMillis),
         TimeHelpers.toYYYYMMDDHHMMSSSSS(rcEvent.getOccurredMillis))
 
       computeBatch()
     }
-    val newTotalCredits = this._userState.totalCredits
+    val newTotalCredits = this._userStateMsg.totalCredits
     if(oldTotalCredits * newTotalCredits < 0)
-      aquarium.eventBus ! new BalanceEvent(this._userState.userID,
+      aquarium.eventBus ! new BalanceEvent(this._userStateMsg.userID,
         newTotalCredits>=0)
-    DEBUG("Updated %s", this._userState)
+    DEBUG("Updated %s", this._userStateMsg)
     logSeparator()
   }
 
   def onGetUserBillRequest(event: GetUserBillRequest): Unit = {
     try{
       val timeslot = event.timeslot
-      val resourceTypes = aquarium.policyStore.
+      val resourceTypes: Map[String, ResourceType] = aquarium.policyStore.
                           loadSortedPolicyModelsWithin(timeslot.from.getTime,
                                                        timeslot.to.getTime).
                           values.headOption match {
           case None => Map[String,ResourceType]()
           case Some(policy:PolicyModel) => policy.resourceTypesMap
       }
-      val state= if(haveUserState) Some(this._userState.msg) else None
+      val state= if(haveUserState) Some(this._userStateMsg) else None
       val billEntryMsg = BillEntryMsg.fromWorkingUserState(timeslot,this._userID,state,resourceTypes)
       //val billEntryMsg = MessageFactory.createBillEntryMsg(billEntry)
       //logger.debug("BILL ENTRY MSG: " + billEntryMsg.toString)
@@ -430,12 +333,14 @@ class UserActor extends ReflectiveRoleableActor {
         // (User CREATEd, with balance state)
         val realtimeMillis = TimeHelpers.nowMillis()
         chargingService.calculateRealtimeUserState(
-          this._userState,
+          this._userAgreementHistoryModel,
+          this._userStateMsg,
           BillingMonthInfo.fromMillis(realtimeMillis),
+          aquarium.resourceMappingAtMillis(realtimeMillis),
           realtimeMillis
         )
 
-        sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this._userID, this._userState.totalCredits)))
+        sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this._userID, this._userStateMsg.totalCredits)))
 
       case (true, false) ⇒
         // (User CREATEd, no balance state)
@@ -444,7 +349,7 @@ class UserActor extends ReflectiveRoleableActor {
           Right(
             GetUserBalanceResponseData(
               this._userID,
-              aquarium.initialUserBalance(this._userCreationIMEvent.getRole, this._userCreationIMEvent.getOccurredMillis)
+              aquarium.initialUserBalance(this.unsafeUserCreationIMEventMsg.getRole, this.unsafeUserCreationIMEventMsg.getOccurredMillis)
             )))
 
       case (false, true) ⇒
@@ -464,12 +369,14 @@ class UserActor extends ReflectiveRoleableActor {
       case true ⇒
         val realtimeMillis = TimeHelpers.nowMillis()
         chargingService.calculateRealtimeUserState(
-          this._userState,
+          this._userAgreementHistoryModel,
+          this._userStateMsg,
           BillingMonthInfo.fromMillis(realtimeMillis),
+          aquarium.resourceMappingAtMillis(realtimeMillis),
           realtimeMillis
         )
 
-        sender ! GetUserStateResponse(Right(this._userState.msg))
+        sender ! GetUserStateResponse(Right(this._userStateMsg))
 
       case false ⇒
         sender ! GetUserStateResponse(Left("No state for user %s [AQU-STA-0006]".format(event.userID)), 404)
@@ -482,8 +389,10 @@ class UserActor extends ReflectiveRoleableActor {
         DEBUG("haveWorkingUserState: %s", event)
         val realtimeMillis = TimeHelpers.nowMillis()
         chargingService.calculateRealtimeUserState(
-          this._userState,
+          this._userAgreementHistoryModel,
+          this._userStateMsg,
           BillingMonthInfo.fromMillis(realtimeMillis),
+          aquarium.resourceMappingAtMillis(realtimeMillis),
           realtimeMillis
         )
 
@@ -491,8 +400,8 @@ class UserActor extends ReflectiveRoleableActor {
           Right(
             GetUserWalletResponseData(
               this._userID,
-              this._userState.totalCredits,
-              MessageFactory.newWalletEntriesMsg(this._userState.msg.getWalletEntries)
+              this._userStateMsg.totalCredits,
+              MessageFactory.newWalletEntriesMsg(this._userStateMsg.getWalletEntries)
             )))
 
       case false ⇒
@@ -504,7 +413,7 @@ class UserActor extends ReflectiveRoleableActor {
               Right(
                 GetUserWalletResponseData(
                   this._userID,
-                  aquarium.initialUserBalance(this._userCreationIMEvent.getRole, this._userCreationIMEvent.getOccurredMillis),
+                  aquarium.initialUserBalance(this.unsafeUserCreationIMEventMsg.getRole, this.unsafeUserCreationIMEventMsg.getOccurredMillis),
                   MessageFactory.newWalletEntriesMsg()
                 )))
 
@@ -515,6 +424,10 @@ class UserActor extends ReflectiveRoleableActor {
     }
   }
 
+  def onSetUserActorUserID(userID: String) {
+    this._userID = userID
+  }
+
   private[this] def D_userID = {
     this._userID
   }
index b0436dd..e6a1aeb 100644 (file)
 package gr.grnet.aquarium.charging
 
 import gr.grnet.aquarium.Aquarium
-import gr.grnet.aquarium.charging.state.UserStateModel
+import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
-import gr.grnet.aquarium.message.avro.gen.{WalletEntryMsg, EffectivePriceTableMsg, FullPriceTableMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
-import gr.grnet.aquarium.uid.{PrefixedUIDGenerator, ConcurrentVMLocalUIDGenerator}
+import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.policy.{EffectivePriceTableModel, FullPriceTableModel}
 
 /**
@@ -89,7 +88,8 @@ trait ChargingBehavior {
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
       resourcesChargingState: ResourcesChargingStateMsg,
-      userStateModel: UserStateModel,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateMsg: UserStateMsg,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
   ): (Int, CreditsModel.Type)
 
index f7f686c..1fc351c 100644 (file)
 
 package gr.grnet.aquarium.charging
 
-import gr.grnet.aquarium.charging.state.{UserStateModel, UserStateBootstrap}
 import gr.grnet.aquarium.computation.BillingMonthInfo
-import gr.grnet.aquarium.message.avro.gen.{ResourcesChargingStateMsg, UserStateMsg, ResourceEventMsg}
-import gr.grnet.aquarium.message.avro.{ModelFactory, MessageFactory, AvroHelpers}
-import gr.grnet.aquarium.policy.ResourceType
+import gr.grnet.aquarium.message.avro.gen.{ResourceTypeMsg, UserStateMsg, ResourceEventMsg}
+import gr.grnet.aquarium.message.avro.{MessageHelpers, MessageFactory, AvroHelpers}
 import gr.grnet.aquarium.util.LogHelpers.Debug
 import gr.grnet.aquarium.util.LogHelpers.DebugSeq
 import gr.grnet.aquarium.util.LogHelpers.Warn
 import gr.grnet.aquarium.util.date.{MutableDateCalc, TimeHelpers}
 import gr.grnet.aquarium.util.{Lifecycle, Loggable}
 import gr.grnet.aquarium.{AquariumInternalError, AquariumAwareSkeleton}
-import java.util.{HashMap ⇒ JHashMap}
+import java.util.{Map ⇒ JMap}
+import gr.grnet.aquarium.event.CreditsModel
+import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 
 /**
  *
@@ -65,30 +65,31 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   //- Lifecycle
 
   def calculateRealtimeUserState(
-      userState: UserStateModel,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateMsg: UserStateMsg,
       billingMonthInfo: BillingMonthInfo,
+      resourceMapping: JMap[String, ResourceTypeMsg],
       realtimeMillis: Long
   ) {
 
     import scala.collection.JavaConverters.mapAsScalaMapConverter
 
-    val stateOfResources = userState.msg.getStateOfResources.asScala
-    val resourceTypesMap = userState.msg.getResourceTypesMap.asScala
+    val stateOfResources = userStateMsg.getStateOfResources.asScala
 
-    for( (resourceTypeName, workingResourcesState) ← stateOfResources) {
-      userState.msg.getResourceTypesMap.get(resourceTypeName) match {
+    for( (resourceName, workingResourcesState) ← stateOfResources) {
+      resourceMapping.get(resourceName) match {
         case null ⇒
           // Ignore
 
-        case resourceType ⇒
-          val chargingBehavior = aquarium.chargingBehaviorOf(resourceType)
+        case resourceTypeMsg ⇒
+          val chargingBehavior = aquarium.chargingBehaviorOf(resourceTypeMsg)
           val stateOfResourceInstance = workingResourcesState.getStateOfResourceInstance.asScala
 
           for((resourceInstanceID, resourceInstanceState) ← stateOfResourceInstance) {
-            Debug(logger, "Realtime calculation for %s, %s", resourceTypeName, resourceInstanceID)
+            Debug(logger, "Realtime calculation for %s, %s", resourceName, resourceInstanceID)
             val virtualEvents = chargingBehavior.createVirtualEventsForRealtimeComputation(
-              userState.userID,
-              resourceTypeName,
+              userStateMsg.getUserID,
+              resourceName,
               resourceInstanceID,
               realtimeMillis,
               resourceInstanceState
@@ -97,8 +98,10 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
             processResourceEvents(
               virtualEvents,
-              userState,
+              userAgreementHistoryModel,
+              userStateMsg,
               billingMonthInfo,
+              resourceMapping,
               realtimeMillis
             )
           }
@@ -107,26 +110,25 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   }
 
   def findOrCalculateWorkingUserStateAtEndOfBillingMonth(
+      userAgreementHistoryModel: UserAgreementHistoryModel,
       billingMonthInfo: BillingMonthInfo,
-      userStateBootstrap: UserStateBootstrap,
-      defaultResourceTypesMap: Map[String, ResourceType],
+      resourceMapping: JMap[String, ResourceTypeMsg],
       userStateRecorder: UserStateMsg ⇒ UserStateMsg
-  ): UserStateModel = {
+  ): UserStateMsg = {
 
-    def computeFullMonthBillingAndSaveState(): UserStateModel = {
+    def computeFullMonthBillingAndSaveState(): UserStateMsg = {
       val fullMonthUserState = replayFullMonthBilling(
-        userStateBootstrap,
+        userAgreementHistoryModel,
         billingMonthInfo,
-        defaultResourceTypesMap,
+        resourceMapping,
         userStateRecorder
       )
 
-      val monthlyUserState0 = UserStateMsg.newBuilder(fullMonthUserState.msg).
+      val monthlyUserState0 = UserStateMsg.newBuilder(fullMonthUserState).
         setIsFullBillingMonth(true).
         setBillingYear(billingMonthInfo.year).
         setBillingMonth(billingMonthInfo.month). // FIXME What about the billingMonthDay?
         setOriginalID("").
-        setResourceTypesMap(MessageFactory.newResourceTypeMsgsMap(defaultResourceTypesMap)).
         build()
 
       // We always save the state when it is a full month billing
@@ -134,11 +136,11 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
       Debug(logger, "Stored full %s %s", billingMonthInfo.toDebugString, AvroHelpers.jsonStringOfSpecificRecord(monthlyUserState1))
 
-      ModelFactory.newUserStateModel(monthlyUserState1)
+      monthlyUserState1
     }
 
-    val userID = userStateBootstrap.userID
-    val userCreationMillis = userStateBootstrap.userCreationMillis
+    val userID = userAgreementHistoryModel.userID
+    val userCreationMillis = userAgreementHistoryModel.unsafeUserCreationMillis
     val userCreationDateCalc = new MutableDateCalc(userCreationMillis)
     val billingMonthStartMillis = billingMonthInfo.monthStartMillis
     val billingMonthStopMillis = billingMonthInfo.monthStopMillis
@@ -149,9 +151,9 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
       // TODO: The initial user state might have already been created.
       //       First ask if it exists and compute only if not
-      val initialUserState0 = MessageFactory.createInitialUserStateMsg(
-        userStateBootstrap,
-        defaultResourceTypesMap,
+      val initialUserState0 = MessageFactory.newInitialUserStateMsg(
+        userID,
+        CreditsModel.from(0.0),
         TimeHelpers.nowMillis()
       )
 
@@ -162,7 +164,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
       Debug(logger, "Stored initial state = %s", AvroHelpers.jsonStringOfSpecificRecord(initialUserState1))
 
-      return ModelFactory.newUserStateModel(initialUserState1)
+      return initialUserState1
     }
 
     // Ask DB cache for the latest known user state for this billing period
@@ -190,7 +192,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
           // ZERO, we are OK!
           case 0 ⇒
             // NOTE: Keep the caller's calculation reason
-            ModelFactory.newUserStateModel(latestUserState)
+            latestUserState
 
           // We had more, so must recompute
           case n if n > 0 ⇒
@@ -210,32 +212,34 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
    * Processes one resource event and computes relevant, incremental charges.
    *
    * @param resourceEvent
-   * @param userStateModel
+   * @param userStateMsg
    * @param billingMonthInfo
    */
   def processResourceEvent(
       resourceEvent: ResourceEventMsg,
-      userStateModel: UserStateModel,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateMsg: UserStateMsg,
       billingMonthInfo: BillingMonthInfo,
-      updateLatestMillis: Boolean
+      updateLatestMillis: Boolean,
+      resourceMapping: JMap[String, ResourceTypeMsg]
   ): Boolean = {
-    logger.warn("processResourceEvent:workingUserState=%s".format(userStateModel)) //
-    val resourceTypeName = resourceEvent.getResource
-    val resourceType = userStateModel.msg.getResourceTypesMap.get(resourceTypeName)
-    if(resourceType eq null) {
+    logger.warn("processResourceEvent:workingUserState=%s".format(userStateMsg)) //
+    val resourceName = resourceEvent.getResource
+    val resourceTypeMsg = resourceMapping.get(resourceName)
+    if(resourceTypeMsg eq null) {
       // Unknown (yet) resource, ignoring event.
       return false
     }
 
-    val chargingBehavior = aquarium.chargingBehaviorOf(resourceType)
-    val resourcesChargingState = userStateModel.msg.getStateOfResources.get(resourceTypeName) match {
+    val chargingBehavior = aquarium.chargingBehaviorOf(resourceTypeMsg)
+    val resourcesChargingState = userStateMsg.getStateOfResources.get(resourceName) match {
       case null ⇒
         // First time for this ChargingBehavior.
-        val newState = new ResourcesChargingStateMsg
-        newState.setResource(resourceTypeName)
-        newState.setDetails(chargingBehavior.initialChargingDetails)
-        newState.setStateOfResourceInstance(new JHashMap())
-        userStateModel.msg.getStateOfResources.put(resourceTypeName,newState)
+        val newState = MessageFactory.newResourcesChargingStateMsg(
+          resourceName,
+          chargingBehavior.initialChargingDetails
+        )
+        userStateMsg.getStateOfResources.put(resourceName, newState)
         newState
       case existingState ⇒
         existingState
@@ -245,28 +249,31 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     val (walletEntriesCount, creditsToSubtract) = chargingBehavior.processResourceEvent(
       aquarium,
       resourceEvent,
-      resourceType,
+      resourceTypeMsg,
       billingMonthInfo,
       resourcesChargingState,
-      userStateModel,
-      msg ⇒ userStateModel.msg.getWalletEntries.add(msg)
+      userAgreementHistoryModel,
+      userStateMsg,
+      msg ⇒ userStateMsg.getWalletEntries.add(msg)
     )
     val m1 = TimeHelpers.nowMillis()
 
     if(updateLatestMillis) {
-      userStateModel.msg.setLatestUpdateMillis(m1)
+      userStateMsg.setLatestUpdateMillis(m1)
     }
 
-    userStateModel.updateLatestResourceEventOccurredMillis(resourceEvent.getOccurredMillis)
-    userStateModel.subtractCredits(creditsToSubtract)
+    MessageHelpers.updateLatestResourceEventOccurredMillis(userStateMsg, resourceEvent.getOccurredMillis)
+    MessageHelpers.subtractCredits(userStateMsg, creditsToSubtract)
 
     true
   }
 
   def processResourceEvents(
       resourceEvents: Traversable[ResourceEventMsg],
-      userState: UserStateModel,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateMsg: UserStateMsg,
       billingMonthInfo: BillingMonthInfo,
+      resourceMapping: JMap[String, ResourceTypeMsg],
       latestUpdateMillis: Long
   ): Unit = {
 
@@ -274,31 +281,33 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     for(currentResourceEvent ← resourceEvents) {
       processResourceEvent(
         currentResourceEvent,
-        userState,
+        userAgreementHistoryModel,
+        userStateMsg,
         billingMonthInfo,
-        false
+        false,
+        resourceMapping
       )
 
       _counter += 1
     }
 
     if(_counter > 0) {
-      userState.msg.setLatestUpdateMillis(latestUpdateMillis)
+      userStateMsg.setLatestUpdateMillis(latestUpdateMillis)
     }
   }
 
   def replayFullMonthBilling(
-      userStateBootstrap: UserStateBootstrap,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
       billingMonthInfo: BillingMonthInfo,
-      defaultResourceTypesMap: Map[String, ResourceType],
+      resourceMapping: JMap[String, ResourceTypeMsg],
       userStateRecorder: UserStateMsg ⇒ UserStateMsg
-  ): UserStateModel = {
+  ): UserStateMsg = {
 
     replayMonthChargingUpTo(
+      userAgreementHistoryModel,
       billingMonthInfo,
       billingMonthInfo.monthStopMillis,
-      userStateBootstrap,
-      defaultResourceTypesMap,
+      resourceMapping,
       userStateRecorder
     )
   }
@@ -309,28 +318,26 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
    *
    * @param billingMonthInfo Which month to bill.
    * @param billingEndTimeMillis Bill from start of month up to (and including) this time.
-   * @param userStateBootstrap
-   * @param resourceTypesMap
    * @param userStateRecorder
    * @return
    */
   def replayMonthChargingUpTo(
+      userAgreementHistoryModel: UserAgreementHistoryModel,
       billingMonthInfo: BillingMonthInfo,
       billingEndTimeMillis: Long,
-      userStateBootstrap: UserStateBootstrap,
-      resourceTypesMap: Map[String, ResourceType],
+      resourceMapping: JMap[String, ResourceTypeMsg],
       userStateRecorder: UserStateMsg ⇒ UserStateMsg
-  ): UserStateModel = {
+  ): UserStateMsg = {
 
     val isFullMonthBilling = billingEndTimeMillis == billingMonthInfo.monthStopMillis
-    val userID = userStateBootstrap.userID
+    val userID = userAgreementHistoryModel.userID
 
     // In order to replay the full month, we start with the state at the beginning of the month.
     val previousBillingMonthInfo = billingMonthInfo.previousMonth
-    val userState = findOrCalculateWorkingUserStateAtEndOfBillingMonth(
+    val userStateMsg = findOrCalculateWorkingUserStateAtEndOfBillingMonth(
+      userAgreementHistoryModel,
       previousBillingMonthInfo,
-      userStateBootstrap,
-      resourceTypesMap,
+      resourceMapping,
       userStateRecorder
     )
 
@@ -339,10 +346,10 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     // specified in the parameters.
     // NOTE: The calculation reason is not the one we get from the previous user state but the one our caller specifies
 
-    Debug(logger, "workingUserState=%s", userState)
+    Debug(logger, "workingUserState=%s", userStateMsg)
     Debug(logger, "previousBillingMonthUserState(%s) = %s",
       previousBillingMonthInfo.toShortDebugString,
-      userState
+      userStateMsg
     )
 
     var _rcEventsCounter = 0
@@ -356,16 +363,18 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
       processResourceEvent(
         currentResourceEvent,
-        userState,
+        userAgreementHistoryModel,
+        userStateMsg,
         billingMonthInfo,
-        false
+        false,
+        resourceMapping
       )
 
       _rcEventsCounter += 1
     }
 
     if(_rcEventsCounter > 0) {
-      userState.msg.setLatestUpdateMillis(TimeHelpers.nowMillis())
+      userStateMsg.setLatestUpdateMillis(TimeHelpers.nowMillis())
     }
 
     Debug(logger, "Found %s resource events for month %s",
@@ -406,6 +415,6 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       workingUserState.totalCredits    = specialWorkingUserState.totalCredits
     }*/
 
-    userState
+    userStateMsg
   }
 }
index df2eeb5..124da45 100644 (file)
 
 package gr.grnet.aquarium.charging
 
-import gr.grnet.aquarium.charging.state.UserStateModel
+import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
 import gr.grnet.aquarium.message.MessageConstants
-import gr.grnet.aquarium.message.avro.gen.{AnyValueMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
+import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.message.avro.{MessageHelpers, AvroHelpers, MessageFactory}
 import gr.grnet.aquarium.util.LogHelpers.Debug
 import gr.grnet.aquarium.{AquariumInternalError, Aquarium}
@@ -117,7 +117,8 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
        resourceType: ResourceTypeMsg,
        billingMonthInfo: BillingMonthInfo,
        resourcesChargingState: ResourcesChargingStateMsg,
-       userStateModel: UserStateModel,
+       userAgreementHistoryModel: UserAgreementHistoryModel,
+       userStateMsg: UserStateMsg,
        walletEntryRecorder: WalletEntryMsg ⇒ Unit
    ): (Int, CreditsModel.Type) = {
 
@@ -132,7 +133,6 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
 
     fillWorkingResourceInstanceChargingStateFromEvent(resourceInstanceChargingState, resourceEvent)
 
-    val userAgreementHistoryModel = userStateModel.userAgreementHistoryModel
     val previousEvents = resourceInstanceChargingState.getPreviousEvents
     val previousEvent = previousEvents.size() match {
       case 0 ⇒
@@ -168,7 +168,7 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       resourceEvent,
       resourceType,
       billingMonthInfo,
-      userStateModel.totalCredits,
+      userStateMsg.getTotalCredits,
       previousEvent.getOccurredMillis,
       resourceEvent.getOccurredMillis,
       userAgreementHistoryModel.agreementByTimeslot,
index c22a1db..c392d13 100644 (file)
 package gr.grnet.aquarium.charging
 
 import gr.grnet.aquarium.Aquarium
-import gr.grnet.aquarium.charging.state.UserStateModel
+import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
-import gr.grnet.aquarium.message.avro.gen.{WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
-import gr.grnet.aquarium.policy.FullPriceTableModel
+import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.message.MessageConstants
 
 /**
@@ -84,7 +83,8 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
       resourcesChargingState: ResourcesChargingStateMsg,
-      userStateModel: UserStateModel,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateMsg: UserStateMsg,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
   ): (Int, Double) = {
     // The credits are given in the value
@@ -101,13 +101,11 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
     val resourceInstanceChargingState = stateOfResourceInstance.get(instanceID)
     fillWorkingResourceInstanceChargingStateFromEvent(resourceInstanceChargingState, resourceEvent)
 
-    val userAgreementHistoryModel = userStateModel.userAgreementHistoryModel
-
     computeWalletEntriesForNewEvent(
       resourceEvent,
       resourceType,
       billingMonthInfo,
-      userStateModel.totalCredits,
+      userStateMsg.getTotalCredits,
       resourceEvent.getOccurredMillis,
       resourceEvent.getOccurredMillis + 1, // single point in time
       userAgreementHistoryModel.agreementByTimeslot,
index da98769..a697b51 100644 (file)
@@ -37,12 +37,12 @@ package gr.grnet.aquarium.charging
 
 import VMChargingBehavior.SelectorLabels.PowerStatus
 import VMChargingBehavior.Selectors.Power
-import gr.grnet.aquarium.charging.state.UserStateModel
+import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.event.CreditsModel
 import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.MessageConstants
-import gr.grnet.aquarium.message.avro.gen.{WalletEntryMsg, ResourceTypeMsg, ResourcesChargingStateMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
+import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourceTypeMsg, ResourcesChargingStateMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.message.avro.{AvroHelpers, MessageHelpers, MessageFactory}
 import gr.grnet.aquarium.util.LogHelpers._
 import gr.grnet.aquarium.{Aquarium, AquariumInternalError}
@@ -137,7 +137,8 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
       resourcesChargingState: ResourcesChargingStateMsg,
-      userStateModel: UserStateModel,
+      userAgreementHistoryModel: UserAgreementHistoryModel,
+      userStateMsg: UserStateMsg,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
   ): (Int, CreditsModel.Type) = {
 
@@ -151,7 +152,6 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
     val resourceInstanceChargingState = stateOfResourceInstance.get(instanceID)
     fillWorkingResourceInstanceChargingStateFromEvent(resourceInstanceChargingState, resourceEvent)
 
-    val userAgreementHistoryModel = userStateModel.userAgreementHistoryModel
     val previousEvents = resourceInstanceChargingState.getPreviousEvents
     val retVal = previousEvents.size() match {
       case 0 ⇒
@@ -165,7 +165,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
           resourceEvent,
           resourceType,
           billingMonthInfo,
-          userStateModel.totalCredits,
+          userStateMsg.getTotalCredits,
           previousEvent.getOccurredMillis,
           resourceEvent.getOccurredMillis,
           userAgreementHistoryModel.agreementByTimeslot,
index f92ca9a..2c30a5d 100644 (file)
@@ -83,12 +83,18 @@ final class UserAgreementHistoryModel(msg: UserAgreementHistoryMsg) {
     }
   }
 
+  def userID = this.msg.getUserID
+
   def latestIMEventOccurredMillis = this._latestIMEventOccurredMillis
 
   def hasUserCreationEvent = this._userCreationIMEventMsgOpt.isDefined
 
   def userCreationIMEvent = this._userCreationIMEventMsgOpt
 
+  def unsafeUserCreationIMEvent = this._userCreationIMEventMsgOpt.get
+
+  def unsafeUserCreationMillis = unsafeUserCreationIMEvent.getOccurredMillis
+
   def size: Int = msg.getAgreements.size()
 
   def agreementByTimeslot: immutable.SortedMap[Timeslot, UserAgreementModel] = {
index 6270b6f..d107f5e 100644 (file)
@@ -44,7 +44,7 @@ import gr.grnet.aquarium.event.CreditsModel
  * @author Christos KK Loverdos <loverdos@gmail.com>
  */
 
-case class UserStateBootstrap(
+final case class UserStateBootstrap(
     initialAgreement: UserAgreementModel,
     initialCredits: CreditsModel.Type
 ) {
index 557d648..ae86d7e 100644 (file)
@@ -47,31 +47,18 @@ import gr.grnet.aquarium.event.CreditsModel
  * @author Christos KK Loverdos <loverdos@gmail.com>
  */
 
-final case class UserStateModel(
-    msg: UserStateMsg,
-    userAgreementHistoryModel: UserAgreementHistoryModel
-) extends JsonSupport {
-
-  def updateLatestResourceEventOccurredMillis(millis: Long): Unit = {
-    if(millis > this.msg.getLatestResourceEventOccurredMillis) {
-      this.msg.setLatestResourceEventOccurredMillis(millis)
-    }
-  }
+final class UserStateModel(msg: UserStateMsg) {
 
   def userID = msg.getUserID
 
   def latestResourceEventOccurredMillis = this.msg.getLatestResourceEventOccurredMillis
 
-  def subtractCredits(credits: CreditsModel.Type) {
-    val oldTotal = CreditsModel.from(msg.getTotalCredits)
-    val newTotal = CreditsModel.-(oldTotal, credits)
-    msg.setTotalCredits(CreditsModel.toTypeInMessage(newTotal))
-  }
-
   @inline final def totalCredits: CreditsModel.Type = {
     CreditsModel.from(msg.getTotalCredits)
   }
 
+  override def toString = msg.toString
+
 //  def newForImplicitEndsAsPreviousEvents(
 //      previousResourceEvents: mutable.Map[(String, String), ResourceEventModel]
 //  ) = {
index 42ea2b5..2c6bb3a 100644 (file)
@@ -41,6 +41,7 @@ import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
 import gr.grnet.aquarium.message.avro.gen._
 import java.{util ⇒ ju}
 import java.util.{ArrayList ⇒ JArrayList}
+import java.util.{HashMap ⇒ JHashMap}
 import scala.collection.JavaConverters.mapAsJavaMapConverter
 import scala.collection.JavaConverters.seqAsJavaListConverter
 import scala.Predef.Map
@@ -278,6 +279,17 @@ object MessageFactory {
     msg
   }
 
+  def newResourcesChargingStateMsg(
+    resourceName: String,
+    initialChargingDetails: DetailsModel.Type
+  ): ResourcesChargingStateMsg = {
+    val msg = new ResourcesChargingStateMsg
+    msg.setResource(resourceName)
+    msg.setDetails(initialChargingDetails)
+    msg.setStateOfResourceInstance(new JHashMap())
+    msg
+  }
+
   def newEmptyUserAgreementHistoryMsg() = {
     val msg = new UserAgreementHistoryMsg
     msg.setAgreements(new ju.ArrayList[UserAgreementMsg]())
@@ -308,7 +320,7 @@ object MessageFactory {
     msg.setValidFromMillis(imEvent.getOccurredMillis)
     msg.setValidToMillis(java.lang.Long.valueOf(java.lang.Long.MAX_VALUE))
     msg.setFullPriceTableRef(null) // get from current (= @imEvent.getOccurredMillis) policy
-    msg.setOccurredMillis(TimeHelpers.nowMillis())
+    msg.setOccurredMillis(java.lang.Long.valueOf(TimeHelpers.nowMillis()))
     msg.setRelatedIMEventMsg(imEvent)
 
     msg
@@ -335,31 +347,30 @@ object MessageFactory {
       setValidFromMillis(millis).
       setValidToMillis(Long.MaxValue).
       setChargingBehaviors(new ju.ArrayList[String]()).
-      setResourceTypes(new ju.ArrayList[ResourceTypeMsg]()).
+      setResourceMapping(new JHashMap()).
       setRoleMapping(new ju.HashMap[String, FullPriceTableMsg]()).
       build()
   }
 
   def newInitialUserStateMsg(
-      usb: UserStateBootstrap,
-      defaultResourceTypesMap: Map[String, ResourceType],
-      occurredMillis: Long
+      userID: String,
+      initialCredits: CreditsModel.Type,
+      occurredMillis: Long,
+      originalID: String = MessageHelpers.UserStateMsgIDGenerator.nextUID()
   ): UserStateMsg = {
 
     val bmi = BillingMonthInfo.fromMillis(occurredMillis)
     val msg = new UserStateMsg
 
-    msg.setUserID(usb.userID)
+    msg.setUserID(userID)
     msg.setOccurredMillis(java.lang.Long.valueOf(occurredMillis))
     msg.setBillingYear(java.lang.Integer.valueOf(bmi.year))
     msg.setBillingMonth(java.lang.Integer.valueOf(bmi.month))
     msg.setBillingMonthDay(java.lang.Integer.valueOf(bmi.day))
-    msg.setTotalCredits(java.lang.Double.valueOf(CreditsModel.toTypeInMessage(usb.initialCredits)))
-    msg.setAgreementHistory(newInitialUserAgreementHistoryMsg(usb.initialAgreement.msg))
+    msg.setTotalCredits(java.lang.Double.valueOf(CreditsModel.toTypeInMessage(initialCredits)))
     msg.setLatestUpdateMillis(java.lang.Long.valueOf(occurredMillis))
     msg.setInStoreID(null)
-    msg.setOriginalID(MessageHelpers.UserStateMsgIDGenerator.nextUID())
-    msg.setResourceTypesMap(newResourceTypeMsgsMap(defaultResourceTypesMap))
+    msg.setOriginalID(originalID)
     msg.setStateOfResources(new java.util.HashMap())
     msg.setWalletEntries(new java.util.ArrayList[WalletEntryMsg]())
     msg
index a22b4ef..ffa3525 100644 (file)
@@ -36,7 +36,7 @@
 package gr.grnet.aquarium.message.avro
 
 import gr.grnet.aquarium.AquariumInternalError
-import gr.grnet.aquarium.event.DetailsModel
+import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
 import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 import gr.grnet.aquarium.message.MessageConstants
 import gr.grnet.aquarium.message.avro.gen.{UserAgreementMsg, UserAgreementHistoryMsg, AnyValueMsg, WalletEntryMsg, EffectivePriceTableMsg, FullPriceTableMsg, ResourceInstanceChargingStateMsg, UserStateMsg, IMEventMsg, ResourceEventMsg}
@@ -104,13 +104,6 @@ final object MessageHelpers {
     msg.getEventType().toLowerCase() == MessageConstants.IMEventMsg.EventTypes.modify
   }
 
-  @inline final def findResourceType(msg: UserStateMsg, name: String) = {
-    msg.getResourceTypesMap.get(name) match {
-      case null         ⇒ None
-      case resourceType ⇒ Some(resourceType)
-    }
-  }
-
   final def setOnePreviousEvent(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
       msg: ResourceEventMsg
@@ -313,6 +306,9 @@ final object MessageHelpers {
     _time
   }
 
+  /**
+   * Use this to update the agreement history. Do not add manually!!
+   */
   def insertUserAgreement(history: UserAgreementHistoryMsg, agreement: UserAgreementMsg) {
     history.getAgreements match {
       case null ⇒
@@ -326,6 +322,13 @@ final object MessageHelpers {
 
     history.setLatestOccurredMillis(latestOccurredMillisOf(history))
     history.setLatestValidFromMillis(latestValidFromMillisOf(history))
+    agreement.getRelatedIMEventMsg match {
+      case null ⇒
+      case imEvent ⇒
+        if(isIMEventCreate(imEvent)) {
+          history.setUserCreationTimeMillis(imEvent.getOccurredMillis)
+        }
+    }
   }
 
   /**
@@ -336,7 +339,21 @@ final object MessageHelpers {
     true
   }
 
-//  final def splitEffectiveUnitPriceTimeslot(
+  def updateLatestResourceEventOccurredMillis(msg: UserStateMsg, millis: Long): Unit = {
+    if(millis > msg.getLatestResourceEventOccurredMillis) {
+      msg.setLatestResourceEventOccurredMillis(millis)
+    }
+  }
+
+  def subtractCredits(msg: UserStateMsg, credits: CreditsModel.Type) {
+    val oldTotal = CreditsModel.from(msg.getTotalCredits)
+    val newTotal = CreditsModel.-(oldTotal, credits)
+    msg.setTotalCredits(CreditsModel.toTypeInMessage(newTotal))
+  }
+
+
+
+  //  final def splitEffectiveUnitPriceTimeslot(
 //      effectiveUnitPrice: EffectiveUnitPriceMsg,
 //      t: Timeslot
 //  ): (List[Timeslot], List[Timeslot]) = {
index f20d984..6fbd46f 100644 (file)
@@ -192,9 +192,6 @@ object ModelFactory {
   }
 
   def newUserStateModel(msg: UserStateMsg): UserStateModel = {
-    UserStateModel(
-      msg,
-      newUserAgreementHistoryModel(msg.getAgreementHistory)
-    )
+    new UserStateModel(msg)
   }
 }
index 63f3b0e..b03c8d5 100644 (file)
@@ -92,13 +92,10 @@ object OrderingHelpers {
 
   final val DefaultUserStateMsgOrdering = new Ordering[UserStateMsg] {
     def compare(x: UserStateMsg, y: UserStateMsg): Int = {
-      val x_getValidFromMillis = x.getAgreementHistory().getAgreements().get(0).getValidFromMillis
-      val y_getValidFromMillis = y.getAgreementHistory().getAgreements().get(0).getValidFromMillis
-
-      if(x_getValidFromMillis < y_getValidFromMillis) {
+      if(x.getOccurredMillis < y.getOccurredMillis) {
         -1
       }
-      else if(x_getValidFromMillis == y_getValidFromMillis) {
+      else if(x.getOccurredMillis == y.getOccurredMillis) {
         0
       } else {
         1
index 490ef14..df1b794 100644 (file)
 package gr.grnet.aquarium.policy
 
 import gr.grnet.aquarium.message.avro.ModelFactory
-import gr.grnet.aquarium.message.avro.gen.{FullPriceTableMsg, PolicyMsg}
+import gr.grnet.aquarium.message.avro.gen.PolicyMsg
 import gr.grnet.aquarium.util.json.JsonSupport
 import scala.collection.JavaConverters.asScalaBufferConverter
+import scala.collection.JavaConverters.mapAsScalaMapConverter
 import scala.collection.immutable
-import gr.grnet.aquarium.AquariumInternalError
 
 /**
  * A policy is the fundamental business-related configuration of Aquarium.
@@ -73,7 +73,7 @@ case class PolicyModel(
   /**
    * All known resource types for the policy's validity period.
    */
-  val resourceTypes = immutable.Set(msg.getResourceTypes().asScala.map(ModelFactory.newResourceType).toSeq: _*)
+  val resourceTypes = immutable.Set(msg.getResourceMapping().asScala.valuesIterator.toSeq.map(ModelFactory.newResourceType).toSeq: _*)
 
   def validFromMillis = msg.getValidFromMillis: Long
 
@@ -98,7 +98,9 @@ case class PolicyModel(
    */
   val roles = roleMapping.keySet
 
-  val resourceTypesMap = immutable.Map(resourceTypes.map(rt ⇒ (rt.name, rt)).toSeq: _*)
+  val resourceTypesMap: Map[String, ResourceType] = {
+    msg.getResourceMapping.asScala.map(kv ⇒ (kv._1, ModelFactory.newResourceType(kv._2))).toMap
+  }
 
   def resourceTypeByName(resource: String) = resourceTypes.find(_.name == resource)
 }
index b065fe8..34289ec 100644 (file)
@@ -61,4 +61,6 @@ trait UserStateStore {
    * Finds the most up-to-date user state for the particular billing period.
    */
   def findLatestUserStateForFullMonthBilling(userID: String, bmi: BillingMonthInfo): Option[UserStateMsg]
+
+  def findLatestUserState(userID: String): Option[UserStateMsg]
 }
\ No newline at end of file
index 2330c45..80caf9c 100644 (file)
@@ -41,7 +41,7 @@ import com.ckkloverdos.props.Props
 import gr.grnet.aquarium.Configurable
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
-import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, IMEventMsg, ResourceEventMsg, PolicyMsg}
+import gr.grnet.aquarium.message.avro.gen.{UserAgreementHistoryMsg, UserStateMsg, IMEventMsg, ResourceEventMsg, PolicyMsg}
 import gr.grnet.aquarium.message.avro.{MessageFactory, MessageHelpers, OrderingHelpers}
 import gr.grnet.aquarium.store._
 import gr.grnet.aquarium.util.{Loggable, Tags}
@@ -97,6 +97,7 @@ extends StoreProvider
   //- StoreProvider
 
 
+
   //+ UserStateStore
   def insertUserState(event: UserStateMsg) = {
     event.setInStoreID(event.getOriginalID)
@@ -116,6 +117,10 @@ extends StoreProvider
       userState.getBillingMonth == bmi.month
     }.lastOption
   }
+
+  def findLatestUserState(userID: String) = {
+    _userStates.filter(_.getUserID == userID).lastOption
+  }
   //- UserStateStore
 
   //+ ResourceEventStore
index 6b46112..c12d5a4 100644 (file)
@@ -41,8 +41,8 @@ import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.converter.StdConverters
 import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 import gr.grnet.aquarium.message.MessageConstants
-import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, IMEventMsg, ResourceEventMsg, PolicyMsg}
-import gr.grnet.aquarium.message.avro.{MessageFactory, OrderingHelpers, AvroHelpers}
+import gr.grnet.aquarium.message.avro.gen.{UserAgreementHistoryMsg, UserStateMsg, IMEventMsg, ResourceEventMsg, PolicyMsg}
+import gr.grnet.aquarium.message.avro.{MessageHelpers, MessageFactory, OrderingHelpers, AvroHelpers}
 import gr.grnet.aquarium.store._
 import gr.grnet.aquarium.util._
 import gr.grnet.aquarium.util.json.JsonSupport
@@ -192,6 +192,21 @@ class MongoDBStore(
     }
   }
 
+  def findLatestUserState(userID: String) = {
+    val query = new BasicDBObjectBuilder().
+      add(MongoDBStore.JsonNames.userID, userID).
+      get()
+
+    // Descending order, so that the latest comes first
+    val sorter = new BasicDBObject(MongoDBStore.JsonNames.occurredMillis, -1)
+
+    val cursor = userStates.find(query).sort(sorter)
+
+    withCloseable(cursor) { cursor ⇒
+      MongoDBStore.findNextPayloadRecord(cursor, new UserStateMsg)
+    }
+  }
+
   /**
    * Stores a user state.
    */
@@ -303,8 +318,6 @@ class MongoDBStore(
   }
   //-IMEventStore
 
-
-
   //+PolicyStore
   def foreachPolicy[U](f: PolicyMsg ⇒ U) {
     val cursor = policies.find()
@@ -360,6 +373,8 @@ object MongoDBStore {
 
   final val UserStateCollection = "userstates"
 
+  final val UserAgreementHistoryCollection = "useragreementhistory"
+
   final val IMEventCollection = "imevents"
 
   final val PolicyCollection = "policies"
index 10be113..655b12e 100644 (file)
@@ -119,6 +119,7 @@ class MongoDBStoreProvider extends StoreProvider with Configurable with Loggable
   def resourceEventStore = _mongoDBStore
   def imEventStore = _mongoDBStore
   def policyStore = _mongoDBStore
+  def userAgreementHistoryStore = _mongoDBStore
 }
 
 /**