Change the representation of computed credit values
authorChristos KK Loverdos <loverdos@gmail.com>
Thu, 27 Sep 2012 13:04:24 +0000 (16:04 +0300)
committerChristos KK Loverdos <loverdos@gmail.com>
Thu, 27 Sep 2012 13:04:24 +0000 (16:04 +0300)
32 files changed:
pom.xml
src/main/avro/aquarium-policy.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/EffectivePriceTableMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/EffectiveUnitPriceMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/FullPriceTableMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/PolicyMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/SelectorValueMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/UserAgreementHistoryMsg.java
src/main/java/gr/grnet/aquarium/message/avro/gen/UserAgreementMsg.java
src/main/scala/gr/grnet/aquarium/Aquarium.scala
src/main/scala/gr/grnet/aquarium/Real.scala [new file with mode: 0644]
src/main/scala/gr/grnet/aquarium/actor/message/GetUserBalanceResponse.scala
src/main/scala/gr/grnet/aquarium/actor/message/GetUserWalletResponse.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/ChargingBehaviorSkeleton.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/bill/BillEntry.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/computation/TimeslotComputations.scala
src/main/scala/gr/grnet/aquarium/event/CreditsModel.scala [deleted file]
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/package.scala [new file with mode: 0644]
src/main/scala/gr/grnet/aquarium/policy/EffectiveUnitPriceModel.scala
src/main/scala/gr/grnet/aquarium/service/AkkaService.scala

diff --git a/pom.xml b/pom.xml
index 42f17be..1b45cc6 100644 (file)
--- a/pom.xml
+++ b/pom.xml
       <plugin>
         <groupId>org.apache.avro</groupId>
         <artifactId>avro-maven-plugin</artifactId>
-        <version>1.7.1</version>
+        <version>1.7.2</version>
         <executions>
           <execution>
             <id>schemas</id>
index 5c77f6b..400ca2b 100644 (file)
@@ -47,7 +47,7 @@ protocol AquariumPolicy {
   }
 
   record EffectiveUnitPriceMsg {
-    double unitPrice; // credits per unit (see ResourceTypeMsg.unit)
+    string unitPrice; // credits per unit (see ResourceTypeMsg.unit)
     union {CronSpecTupleMsg, null} when;
   }
 
index 62f534d..ddc0c3e 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\":\"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\":{}}");
+  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\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[\"CronSpecTupleMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":\"EffectiveUnitPriceMsg\"}}]},{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[\"EffectivePriceTableMsg\",{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"PolicyMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"resourceMapping\",\"type\":{\"type\":\"map\",\"values\":\"ResourceTypeMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":\"FullPriceTableMsg\",\"avro.java.string\":\"String\"}}]}],\"messages\":{}}");
 
   @SuppressWarnings("all")
   public interface Callback extends AquariumPolicy {
index 8b2e639..9bc13d9 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\":\"resourceMapping\",\"type\":{\"type\":\"map\",\"values\":\"ResourceTypeMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":\"FullPriceTableMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"DetailsMsg\",\"fields\":[{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementMsg\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"relatedIMEventOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"fullPriceTableRef\",\"type\":[\"FullPriceTableMsg\",\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[\"IMEventMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"ResourceInstanceChargingStateMsg\",\"fields\":[{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"previousEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"implicitlyIssuedStartEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"accumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldAccumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"previousValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"currentValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourcesChargingStateMsg\",\"fields\":[{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResourceInstance\",\"type\":{\"type\":\"map\",\"values\":\"ResourceInstanceChargingStateMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementHistoryMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"latestOccurredMillis\",\"type\":\"long\"},{\"name\":\"latestValidFromMillis\",\"type\":\"long\"},{\"name\":\"userCreationTimeMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"agreements\",\"type\":{\"type\":\"array\",\"items\":\"UserAgreementMsg\"}}]},{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]},{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":\"ChargeslotMsg\"}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":\"ResourceTypeMsg\"},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false}]},{\"type\":\"record\",\"name\":\"WalletEntriesMsg\",\"fields\":[{\"name\":\"entries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]},{\"type\":\"record\",\"name\":\"UserStateMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"parentOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentInStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"isFirst\",\"type\":\"boolean\",\"default\":false},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":\"ResourcesChargingStateMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0},{\"name\":\"latestUpdateMillis\",\"type\":\"long\"},{\"name\":\"latestResourceEventOccurredMillis\",\"type\":\"long\"},{\"name\":\"billingPeriodOutOfSyncResourceEventsCounter\",\"type\":\"long\",\"default\":0},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"isFullBillingMonth\",\"type\":\"boolean\",\"default\":false},{\"name\":\"walletEntries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]}],\"messages\":{}}");
+  public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"AquariumUserState\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"types\":[{\"type\":\"record\",\"name\":\"ResourceTypeMsg\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"unit\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviorClass\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[\"CronSpecTupleMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":\"EffectiveUnitPriceMsg\"}}]},{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[\"EffectivePriceTableMsg\",{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"PolicyMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"resourceMapping\",\"type\":{\"type\":\"map\",\"values\":\"ResourceTypeMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"chargingBehaviors\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"roleMapping\",\"type\":{\"type\":\"map\",\"values\":\"FullPriceTableMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"AnyValueMsg\",\"fields\":[{\"name\":\"anyValue\",\"type\":[\"null\",\"int\",\"long\",\"boolean\",\"double\",\"bytes\",{\"type\":\"string\",\"avro.java.string\":\"String\"},{\"type\":\"array\",\"items\":\"AnyValueMsg\"},{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}]}]},{\"type\":\"record\",\"name\":\"DetailsMsg\",\"fields\":[{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourceEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"value\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementMsg\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"relatedIMEventOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"fullPriceTableRef\",\"type\":[\"FullPriceTableMsg\",\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[\"IMEventMsg\",\"null\"]}]},{\"type\":\"record\",\"name\":\"ResourceInstanceChargingStateMsg\",\"fields\":[{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"instanceID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"previousEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"implicitlyIssuedStartEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"accumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldAccumulatingAmount\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"previousValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"currentValue\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"ResourcesChargingStateMsg\",\"fields\":[{\"name\":\"resource\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":\"AnyValueMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"stateOfResourceInstance\",\"type\":{\"type\":\"map\",\"values\":\"ResourceInstanceChargingStateMsg\",\"avro.java.string\":\"String\"}}]},{\"type\":\"record\",\"name\":\"UserAgreementHistoryMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"latestOccurredMillis\",\"type\":\"long\"},{\"name\":\"latestValidFromMillis\",\"type\":\"long\"},{\"name\":\"userCreationTimeMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"agreements\",\"type\":{\"type\":\"array\",\"items\":\"UserAgreementMsg\"}}]},{\"type\":\"record\",\"name\":\"ChargeslotMsg\",\"fields\":[{\"name\":\"startMillis\",\"type\":\"long\"},{\"name\":\"stopMillis\",\"type\":\"long\"},{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"explanation\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"\"},{\"name\":\"creditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.0}]},{\"type\":\"record\",\"name\":\"WalletEntryMsg\",\"fields\":[{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"sumOfCreditsToSubtract\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"oldTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"newTotalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"whenComputedMillis\",\"type\":\"long\"},{\"name\":\"referenceStartMillis\",\"type\":\"long\"},{\"name\":\"referenceStopMillis\",\"type\":\"long\"},{\"name\":\"billingYear\",\"type\":\"int\"},{\"name\":\"billingMonth\",\"type\":\"int\"},{\"name\":\"billingMonthDay\",\"type\":\"int\"},{\"name\":\"chargeslots\",\"type\":{\"type\":\"array\",\"items\":\"ChargeslotMsg\"}},{\"name\":\"resourceEvents\",\"type\":{\"type\":\"array\",\"items\":\"ResourceEventMsg\"}},{\"name\":\"resourceType\",\"type\":\"ResourceTypeMsg\"},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false}]},{\"type\":\"record\",\"name\":\"WalletEntriesMsg\",\"fields\":[{\"name\":\"entries\",\"type\":{\"type\":\"array\",\"items\":\"WalletEntryMsg\"}}]},{\"type\":\"record\",\"name\":\"UserStateMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"parentOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"parentInStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"isFirst\",\"type\":\"boolean\",\"default\":false},{\"name\":\"stateOfResources\",\"type\":{\"type\":\"map\",\"values\":\"ResourcesChargingStateMsg\",\"avro.java.string\":\"String\"}},{\"name\":\"totalCredits\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":0.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 8f542c2..8f4f2be 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class EffectivePriceTableMsg 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\":\"EffectivePriceTableMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"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\"]}]}}}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]}");
   @Deprecated public java.util.List<gr.grnet.aquarium.message.avro.gen.EffectiveUnitPriceMsg> priceOverrides;
 
   /**
index 0d0a78f..0caaa83 100644 (file)
@@ -6,8 +6,8 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class EffectiveUnitPriceMsg 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\":\"EffectiveUnitPriceMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"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\"]}]}");
-  @Deprecated public double unitPrice;
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}");
+  @Deprecated public java.lang.String unitPrice;
   @Deprecated public gr.grnet.aquarium.message.avro.gen.CronSpecTupleMsg when;
 
   /**
@@ -18,7 +18,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
   /**
    * All-args constructor.
    */
-  public EffectiveUnitPriceMsg(java.lang.Double unitPrice, gr.grnet.aquarium.message.avro.gen.CronSpecTupleMsg when) {
+  public EffectiveUnitPriceMsg(java.lang.String unitPrice, gr.grnet.aquarium.message.avro.gen.CronSpecTupleMsg when) {
     this.unitPrice = unitPrice;
     this.when = when;
   }
@@ -36,7 +36,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
   @SuppressWarnings(value="unchecked")
   public void put(int field$, java.lang.Object value$) {
     switch (field$) {
-    case 0: unitPrice = (java.lang.Double)value$; break;
+    case 0: unitPrice = (java.lang.String)value$; break;
     case 1: when = (gr.grnet.aquarium.message.avro.gen.CronSpecTupleMsg)value$; break;
     default: throw new org.apache.avro.AvroRuntimeException("Bad index");
     }
@@ -45,7 +45,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
   /**
    * Gets the value of the 'unitPrice' field.
    */
-  public java.lang.Double getUnitPrice() {
+  public java.lang.String getUnitPrice() {
     return unitPrice;
   }
 
@@ -53,7 +53,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
    * Sets the value of the 'unitPrice' field.
    * @param value the value to set.
    */
-  public void setUnitPrice(java.lang.Double value) {
+  public void setUnitPrice(java.lang.String value) {
     this.unitPrice = value;
   }
 
@@ -93,7 +93,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
   public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<EffectiveUnitPriceMsg>
     implements org.apache.avro.data.RecordBuilder<EffectiveUnitPriceMsg> {
 
-    private double unitPrice;
+    private java.lang.String unitPrice;
     private gr.grnet.aquarium.message.avro.gen.CronSpecTupleMsg when;
 
     /** Creates a new Builder */
@@ -110,7 +110,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
     private Builder(gr.grnet.aquarium.message.avro.gen.EffectiveUnitPriceMsg other) {
             super(gr.grnet.aquarium.message.avro.gen.EffectiveUnitPriceMsg.SCHEMA$);
       if (isValidValue(fields()[0], other.unitPrice)) {
-        this.unitPrice = (java.lang.Double) data().deepCopy(fields()[0].schema(), other.unitPrice);
+        this.unitPrice = (java.lang.String) data().deepCopy(fields()[0].schema(), other.unitPrice);
         fieldSetFlags()[0] = true;
       }
       if (isValidValue(fields()[1], other.when)) {
@@ -120,12 +120,12 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
     }
 
     /** Gets the value of the 'unitPrice' field */
-    public java.lang.Double getUnitPrice() {
+    public java.lang.String getUnitPrice() {
       return unitPrice;
     }
     
     /** Sets the value of the 'unitPrice' field */
-    public gr.grnet.aquarium.message.avro.gen.EffectiveUnitPriceMsg.Builder setUnitPrice(double value) {
+    public gr.grnet.aquarium.message.avro.gen.EffectiveUnitPriceMsg.Builder setUnitPrice(java.lang.String value) {
       validate(fields()[0], value);
       this.unitPrice = value;
       fieldSetFlags()[0] = true;
@@ -139,6 +139,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
     
     /** Clears the value of the 'unitPrice' field */
     public gr.grnet.aquarium.message.avro.gen.EffectiveUnitPriceMsg.Builder clearUnitPrice() {
+      unitPrice = null;
       fieldSetFlags()[0] = false;
       return this;
     }
@@ -172,7 +173,7 @@ public class EffectiveUnitPriceMsg extends org.apache.avro.specific.SpecificReco
     public EffectiveUnitPriceMsg build() {
       try {
         EffectiveUnitPriceMsg record = new EffectiveUnitPriceMsg();
-        record.unitPrice = fieldSetFlags()[0] ? this.unitPrice : (java.lang.Double) defaultValue(fields()[0]);
+        record.unitPrice = fieldSetFlags()[0] ? this.unitPrice : (java.lang.String) defaultValue(fields()[0]);
         record.when = fieldSetFlags()[1] ? this.when : (gr.grnet.aquarium.message.avro.gen.CronSpecTupleMsg) defaultValue(fields()[1]);
         return record;
       } catch (Exception e) {
index 441fd00..21611ae 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class FullPriceTableMsg 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\":\"FullPriceTableMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"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\"}}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]},{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]}");
   @Deprecated public java.util.Map<java.lang.String,java.util.Map<java.lang.String,gr.grnet.aquarium.message.avro.gen.SelectorValueMsg>> perResource;
 
   /**
index 4d757eb..06fff1f 100644 (file)
@@ -6,7 +6,7 @@
 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\":\"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\"}}]}");
+  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\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]},{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},\"avro.java.string\":\"String\"}}]}");
   @Deprecated public java.lang.String originalID;
   @Deprecated public java.lang.String inStoreID;
   @Deprecated public java.lang.String parentID;
index c0b0aee..f51cf11 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class SelectorValueMsg 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\":\"SelectorValueMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"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\"}]}]}");
+  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]},{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]}");
   @Deprecated public java.lang.Object selectorValue;
 
   /**
index 4347e0e..81d2dda 100644 (file)
@@ -6,7 +6,7 @@
 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\":\"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\"]}]}}}]}");
+  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\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]},{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"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;
index 8ff1230..8833821 100644 (file)
@@ -6,7 +6,7 @@
 package gr.grnet.aquarium.message.avro.gen;  
 @SuppressWarnings("all")
 public class UserAgreementMsg 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\":\"UserAgreementMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"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\":\"UserAgreementMsg\",\"namespace\":\"gr.grnet.aquarium.message.avro.gen\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"relatedIMEventOriginalID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"occurredMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"validFromMillis\",\"type\":\"long\"},{\"name\":\"validToMillis\",\"type\":\"long\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"fullPriceTableRef\",\"type\":[{\"type\":\"record\",\"name\":\"FullPriceTableMsg\",\"fields\":[{\"name\":\"perResource\",\"type\":{\"type\":\"map\",\"values\":{\"type\":\"map\",\"values\":{\"type\":\"record\",\"name\":\"SelectorValueMsg\",\"fields\":[{\"name\":\"selectorValue\",\"type\":[{\"type\":\"record\",\"name\":\"EffectivePriceTableMsg\",\"fields\":[{\"name\":\"priceOverrides\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"EffectiveUnitPriceMsg\",\"fields\":[{\"name\":\"unitPrice\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"when\",\"type\":[{\"type\":\"record\",\"name\":\"CronSpecTupleMsg\",\"fields\":[{\"name\":\"a\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"b\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]},\"null\"]}]}}}]},{\"type\":\"map\",\"values\":\"SelectorValueMsg\",\"avro.java.string\":\"String\"}]}]},\"avro.java.string\":\"String\"},\"avro.java.string\":\"String\"}}]},\"null\"]},{\"name\":\"relatedIMEventMsg\",\"type\":[{\"type\":\"record\",\"name\":\"IMEventMsg\",\"fields\":[{\"name\":\"originalID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"inStoreID\",\"type\":[{\"type\":\"string\",\"avro.java.string\":\"String\"},\"null\"]},{\"name\":\"occurredMillis\",\"type\":\"long\"},{\"name\":\"receivedMillis\",\"type\":\"long\",\"default\":0},{\"name\":\"userID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"clientID\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"eventVersion\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"default\":\"1.0\"},{\"name\":\"eventType\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isActive\",\"type\":\"boolean\"},{\"name\":\"role\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"isSynthetic\",\"type\":\"boolean\",\"default\":false},{\"name\":\"details\",\"type\":{\"type\":\"map\",\"values\":{\"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 id;
   @Deprecated public java.lang.String relatedIMEventOriginalID;
   @Deprecated public java.lang.String userID;
index 19c1c71..3f735d5 100644 (file)
@@ -54,7 +54,6 @@ import gr.grnet.aquarium.util.{Loggable, Lifecycle}
 import java.io.File
 import java.util.concurrent.atomic.AtomicBoolean
 import org.slf4j.{LoggerFactory, Logger}
-import gr.grnet.aquarium.event.CreditsModel
 import gr.grnet.aquarium.charging.state.UserStateBootstrap
 import java.util.{Map ⇒ JMap}
 import java.util.{HashMap ⇒ JHashMap}
@@ -424,9 +423,9 @@ final class Aquarium(env: Env) extends Lifecycle with Loggable {
     ModelFactory.newUserAgreementModelFromIMEvent(imEvent)
   }
 
-  def initialUserBalance(role: String, referenceTimeMillis: Long): CreditsModel.Type = {
+  def initialUserBalance(role: String, referenceTimeMillis: Long): Real = {
     // FIXME: Where is the mapping?
-    CreditsModel.from(0.0)
+    Real.Zero
   }
 
   def getUserStateBootstrap(imEvent: IMEventMsg): UserStateBootstrap = {
diff --git a/src/main/scala/gr/grnet/aquarium/Real.scala b/src/main/scala/gr/grnet/aquarium/Real.scala
new file mode 100644 (file)
index 0000000..306871c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *
+ *  * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *  *
+ *  * Redistribution and use in source and binary forms, with or
+ *  * without modification, are permitted provided that the following
+ *  * conditions are met:
+ *  *
+ *  *   1. Redistributions of source code must retain the above
+ *  *      copyright notice, this list of conditions and the following
+ *  *      disclaimer.
+ *  *
+ *  *   2. Redistributions in binary form must reproduce the above
+ *  *      copyright notice, this list of conditions and the following
+ *  *      disclaimer in the documentation and/or other materials
+ *  *      provided with the distribution.
+ *  *
+ *  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ *  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ *  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ *  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ *  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  * POSSIBILITY OF SUCH DAMAGE.
+ *  *
+ *  * The views and conclusions contained in the software and
+ *  * documentation are those of the authors and should not be
+ *  * interpreted as representing official policies, either expressed
+ *  * or implied, of GRNET S.A.
+ *
+ */
+
+package gr.grnet.aquarium
+
+import java.math.MathContext
+
+/**
+ *
+ * @author Christos KK Loverdos <loverdos@gmail.com>
+ */
+final object Real {
+  final val Zero = this(0)
+  final val One  = this(1)
+  final val _1K  = this(1024)
+  final val _1M  = _1K * _1K
+  final val _1G  = _1M * _1K
+
+  final val HourMillis = Real(1000L * 60 * 60)
+  final val HourMillisInverse = Real.One / HourMillis
+  final val MB = _1M
+  final val MBInverse = One / MB
+  final val GB = _1G
+  final val GBInverse = One / GB
+
+
+  @inline final def apply(v: java.math.BigDecimal) = {
+    new BigDecimal(v, MathContext.UNLIMITED)
+  }
+
+  @inline final def apply(v: String): Real = this(new java.math.BigDecimal(v))
+
+  @inline final def apply(v: Double): Real = this(new java.math.BigDecimal(v))
+
+  @inline final def apply(v: Long): Real = this(new java.math.BigDecimal(v))
+
+  @inline final def apply(v: Int): Real = this(new java.math.BigDecimal(v))
+
+  @inline final def toMsgField(v: Real): String = v.toString()
+
+  @inline final def toMsgField(v: Double): String = v.toString()
+
+  @inline final def fromMsgField(v: String): Real = this(v)
+}
+
+
index 9b29c23..e1158d8 100644 (file)
@@ -55,4 +55,4 @@ extends UserActorResponseMessage(balance, suggestedHTTPStatus) {
   }
 }
 
-case class GetUserBalanceResponseData(userID: String, balance: Double)
+case class GetUserBalanceResponseData(userID: String, balance: String)
index 765712b..a420c8f 100644 (file)
@@ -56,4 +56,4 @@ extends UserActorResponseMessage(state, suggestedHTTPStatus) {
   }
 }
 
-case class GetUserWalletResponseData(userID: String, credits: Double, walletEntries: WalletEntriesMsg)
\ No newline at end of file
+case class GetUserWalletResponseData(userID: String, credits: String, walletEntries: WalletEntriesMsg)
\ No newline at end of file
index b19a4da..3fde4f6 100644 (file)
@@ -37,7 +37,7 @@ package gr.grnet.aquarium.actor
 package service
 package user
 
-import gr.grnet.aquarium.AquariumInternalError
+import gr.grnet.aquarium.{Real, AquariumInternalError}
 import gr.grnet.aquarium.actor.message.GetUserBalanceRequest
 import gr.grnet.aquarium.actor.message.GetUserBalanceResponse
 import gr.grnet.aquarium.actor.message.GetUserBalanceResponseData
@@ -51,7 +51,6 @@ import gr.grnet.aquarium.actor.message.GetUserWalletResponse
 import gr.grnet.aquarium.actor.message.GetUserWalletResponseData
 import gr.grnet.aquarium.actor.message.config.AquariumPropertiesLoaded
 import gr.grnet.aquarium.charging.state.{UserStateModel, UserAgreementHistoryModel, UserStateBootstrap}
-import gr.grnet.aquarium.computation.BillingMonthInfo
 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
@@ -59,8 +58,6 @@ 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,18 +65,16 @@ import java.util
  */
 
 class UserActor extends ReflectiveRoleableActor {
-  private[this] var _rcMsgCount = 0
   private[this] var _imMsgCount = 0
-  private[this] var _userID: String = "???"
   private[this] var _userStateMsg: UserStateMsg = _
   private[this] var _userAgreementHistoryModel: UserAgreementHistoryModel = _
 
-  def unsafeUserID = {
-    if(!haveUserID) {
+  def userID = {
+    if(!haveUserState) {
       throw new AquariumInternalError("%s not initialized")
     }
 
-    this._userID
+    this._userStateMsg.getUserID
   }
 
   override def postStop() {
@@ -88,7 +83,7 @@ class UserActor extends ReflectiveRoleableActor {
   }
 
   private[this] def shutmedown(): Unit = {
-    if(haveUserID) {
+    if(haveUserState) {
       aquarium.akkaService.invalidateUserActor(this)
     }
   }
@@ -104,34 +99,14 @@ class UserActor extends ReflectiveRoleableActor {
 
   private[this] def chargingService = aquarium.chargingService
 
-  private[this] def stdUserStateStoreFunc = (userState: UserStateMsg) ⇒ {
-    aquarium.userStateStore.insertUserState(userState)
-  }
-
   def onAquariumPropertiesLoaded(event: AquariumPropertiesLoaded): Unit = {
   }
 
-  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
 
-  private[this] def createInitialUserStateMsgFromCreateIMEvent() {
-    assert(haveAgreements, "haveAgreements")
-    assert(isUserCreated, "isUserCreated")
-    assert(this._userAgreementHistoryModel.hasUserCreationEvent, "this._userAgreementHistoryModel.hasUserCreationEvent")
-
-    val userCreationIMEventMsg = unsafeUserCreationIMEventMsg
-    val userStateBootstrap = aquarium.getUserStateBootstrap(userCreationIMEventMsg)
-
-    this._userStateMsg = MessageFactory.newInitialUserStateMsg(
-      this._userID,
-      CreditsModel.from(0.0),
-      TimeHelpers.nowMillis()
-    )
-  }
-
   /**
    * Creates the agreement history from all the stored IMEvents.
    *
@@ -139,12 +114,14 @@ class UserActor extends ReflectiveRoleableActor {
    */
   private[this] def createUserAgreementHistoryFromStoredIMEvents(): (Boolean, Int) = {
     DEBUG("createUserAgreementHistoryFromStoredIMEvents()")
-    val historyMsg = MessageFactory.newUserAgreementHistoryMsg(this._userID)
+    assert(haveUserState, "haveUserState")
+
+    val historyMsg = MessageFactory.newUserAgreementHistoryMsg(userID)
     this._userAgreementHistoryModel = ModelFactory.newUserAgreementHistoryModel(historyMsg)
 
     var _imcounter = 0
 
-    val hadCreateEvent = aquarium.imEventStore.foreachIMEventInOccurrenceOrder(this._userID) { imEvent ⇒
+    val hadCreateEvent = aquarium.imEventStore.foreachIMEventInOccurrenceOrder(userID) { imEvent ⇒
       _imcounter += 1
       DEBUG("Replaying [%s/%s] %s", shortClassNameOf(imEvent), _imcounter, imEvent)
 
@@ -219,86 +196,26 @@ class UserActor extends ReflectiveRoleableActor {
       return
     }
 
-    val now = TimeHelpers.nowMillis()
-    val resourceMapping = aquarium.resourceMappingAtMillis(now)
-
-    val nowBillingMonthInfo = BillingMonthInfo.fromMillis(now)
-    val nowYear = nowBillingMonthInfo.year
-    val nowMonth = nowBillingMonthInfo.month
+    assert(haveUserState, "haveUserState")
 
-    val eventOccurredMillis = rcEvent.getOccurredMillis
-    val eventBillingMonthInfo = BillingMonthInfo.fromMillis(eventOccurredMillis)
-    val eventYear = eventBillingMonthInfo.year
-    val eventMonth = eventBillingMonthInfo.month
+    val oldTotalCredits = Real(this._userStateMsg.getTotalCredits)
 
-    def computeBatch(): Unit = {
-      DEBUG("Going for out of sync charging for %s", rcEvent.getOriginalID)
-
-      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,
-        resourceMapping,
-        stdUserStateStoreFunc
-      )
+    chargingService.processResourceEvent(
+      rcEvent.getReceivedMillis,
+      rcEvent,
+      this._userAgreementHistoryModel,
+      this._userStateMsg,
+      aquarium.currentResourceMapping,
+      true
+    )
 
-    }
+    val newTotalCredits = Real(this._userStateMsg.getTotalCredits)
 
-    def computeRealtime(): Unit = {
-      DEBUG("Going for in sync charging for %s", rcEvent.getOriginalID)
-      chargingService.processResourceEvent(
-        rcEvent,
-        this._userAgreementHistoryModel,
-        this._userStateMsg,
-        nowBillingMonthInfo,
-        true,
-        resourceMapping
-      )
-
-      this._rcMsgCount += 1
+    if(oldTotalCredits.signum * newTotalCredits.signum < 0) {
+      aquarium.eventBus ! new BalanceEvent(userID, newTotalCredits >= 0)
     }
 
-    val oldTotalCredits =
-      if(this._userStateMsg!=null)
-        this._userStateMsg.totalCredits
-      else
-        0.0D
-    // FIXME check these
-    if(this._userStateMsg eq null) {
-      computeBatch()
-    }
-    else if(nowYear != eventYear || nowMonth != eventMonth) {
-      DEBUG(
-        "nowYear(%s) != eventYear(%s) || nowMonth(%s) != eventMonth(%s)",
-        nowYear, eventYear,
-        nowMonth, eventMonth
-      )
-      computeBatch()
-    }
-    else if(this._userStateMsg.latestResourceEventOccurredMillis < rcEvent.getOccurredMillis) {
-      DEBUG("this._workingUserState.latestResourceEventOccurredMillis < rcEvent.occurredMillis")
-      DEBUG(
-        "%s < %s",
-        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._userStateMsg.latestResourceEventOccurredMillis),
-        TimeHelpers.toYYYYMMDDHHMMSSSSS(rcEvent.getOccurredMillis))
-
-      computeBatch()
-    }
-    val newTotalCredits = this._userStateMsg.totalCredits
-    if(oldTotalCredits * newTotalCredits < 0)
-      aquarium.eventBus ! new BalanceEvent(this._userStateMsg.userID,
-        newTotalCredits>=0)
     DEBUG("Updated %s", this._userStateMsg)
-    logSeparator()
   }
 
   def onGetUserBillRequest(event: GetUserBillRequest): Unit = {
@@ -312,10 +229,10 @@ class UserActor extends ReflectiveRoleableActor {
           case Some(policy:PolicyModel) => policy.resourceTypesMap
       }
       val state= if(haveUserState) Some(this._userStateMsg) else None
-      val billEntryMsg = BillEntryMsg.fromWorkingUserState(timeslot,this._userID,state,resourceTypes)
+      val billEntryMsg = BillEntryMsg.fromWorkingUserState(timeslot,this.userID,state,resourceTypes)
       //val billEntryMsg = MessageFactory.createBillEntryMsg(billEntry)
       //logger.debug("BILL ENTRY MSG: " + billEntryMsg.toString)
-      val billData = GetUserBillResponseData(this._userID,billEntryMsg)
+      val billData = GetUserBillResponseData(this.userID,billEntryMsg)
       sender ! GetUserBillResponse(Right(billData))
     } catch {
       case e:Exception =>
@@ -334,12 +251,11 @@ class UserActor extends ReflectiveRoleableActor {
         chargingService.calculateRealtimeUserState(
           this._userAgreementHistoryModel,
           this._userStateMsg,
-          BillingMonthInfo.fromMillis(realtimeMillis),
-          aquarium.resourceMappingAtMillis(realtimeMillis),
+          aquarium.currentResourceMapping,
           realtimeMillis
         )
 
-        sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this._userID, this._userStateMsg.totalCredits)))
+        sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this.userID, this._userStateMsg.getTotalCredits)))
 
       case (true, false) ⇒
         // (User CREATEd, no balance state)
@@ -347,8 +263,8 @@ class UserActor extends ReflectiveRoleableActor {
         sender ! GetUserBalanceResponse(
           Right(
             GetUserBalanceResponseData(
-              this._userID,
-              aquarium.initialUserBalance(this.unsafeUserCreationIMEventMsg.getRole, this.unsafeUserCreationIMEventMsg.getOccurredMillis)
+              this.userID,
+              aquarium.initialUserBalance(this.unsafeUserCreationIMEventMsg.getRole, this.unsafeUserCreationIMEventMsg.getOccurredMillis).toString()
             )))
 
       case (false, true) ⇒
@@ -370,8 +286,7 @@ class UserActor extends ReflectiveRoleableActor {
         chargingService.calculateRealtimeUserState(
           this._userAgreementHistoryModel,
           this._userStateMsg,
-          BillingMonthInfo.fromMillis(realtimeMillis),
-          aquarium.resourceMappingAtMillis(realtimeMillis),
+          aquarium.currentResourceMapping,
           realtimeMillis
         )
 
@@ -390,16 +305,15 @@ class UserActor extends ReflectiveRoleableActor {
         chargingService.calculateRealtimeUserState(
           this._userAgreementHistoryModel,
           this._userStateMsg,
-          BillingMonthInfo.fromMillis(realtimeMillis),
-          aquarium.resourceMappingAtMillis(realtimeMillis),
+          aquarium.currentResourceMapping,
           realtimeMillis
         )
 
         sender ! GetUserWalletResponse(
           Right(
             GetUserWalletResponseData(
-              this._userID,
-              this._userStateMsg.totalCredits,
+              this.userID,
+              this._userStateMsg.getTotalCredits,
               MessageFactory.newWalletEntriesMsg(this._userStateMsg.getWalletEntries)
             )))
 
@@ -411,8 +325,8 @@ class UserActor extends ReflectiveRoleableActor {
             sender ! GetUserWalletResponse(
               Right(
                 GetUserWalletResponseData(
-                  this._userID,
-                  aquarium.initialUserBalance(this.unsafeUserCreationIMEventMsg.getRole, this.unsafeUserCreationIMEventMsg.getOccurredMillis),
+                  this.userID,
+                  Real.toMsgField(aquarium.initialUserBalance(this.unsafeUserCreationIMEventMsg.getRole, this.unsafeUserCreationIMEventMsg.getOccurredMillis)),
                   MessageFactory.newWalletEntriesMsg()
                 )))
 
@@ -424,11 +338,15 @@ class UserActor extends ReflectiveRoleableActor {
   }
 
   def onSetUserActorUserID(userID: String) {
-    this._userID = userID
+    this._userStateMsg = MessageFactory.newInitialUserStateMsg(
+      userID,
+      Real.Zero,
+      TimeHelpers.nowMillis()
+    )
   }
 
   private[this] def D_userID = {
-    this._userID
+    if(haveUserState) userID else "???"
   }
 
   private[this] def DEBUG(fmt: String, args: Any*) =
index e6a1aeb..96c27bd 100644 (file)
 package gr.grnet.aquarium.charging
 
 import gr.grnet.aquarium.Aquarium
+import gr.grnet.aquarium.Real
 import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
-import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
+import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.policy.{EffectivePriceTableModel, FullPriceTableModel}
 
@@ -64,7 +65,7 @@ trait ChargingBehavior {
       currentResourceEvent: ResourceEventMsg,
       referenceStartMillis: Long,
       referenceStopMillis: Long,
-      totalCredits: CreditsModel.Type
+      totalCredits: Real
   ): List[String]
 
   def selectEffectivePriceTableModel(
@@ -74,7 +75,7 @@ trait ChargingBehavior {
       currentResourceEvent: ResourceEventMsg,
       referenceStartMillis: Long,
       referenceStopMillis: Long,
-      totalCredits: Double
+      totalCredits: Real
   ): EffectivePriceTableModel
 
   /**
@@ -91,14 +92,14 @@ trait ChargingBehavior {
       userAgreementHistoryModel: UserAgreementHistoryModel,
       userStateMsg: UserStateMsg,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
-  ): (Int, CreditsModel.Type)
+  ): (Int, Real)
 
   def computeCreditsToSubtract(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
-      oldCredits: CreditsModel.Type,
+      oldCredits: Real,
       timeDeltaMillis: Long,
-      unitPrice: Double
-  ): (CreditsModel.Type, String /* explanation */)
+      unitPrice: Real
+  ): (Real, String /* explanation */)
 
   /**
    * Given the charging state of a resource instance and the details of the incoming message, compute the new
@@ -107,7 +108,7 @@ trait ChargingBehavior {
   def computeNewAccumulatingAmount(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
       eventDetails: DetailsModel.Type
-  ): CreditsModel.Type
+  ): Real
 
   def createVirtualEventsForRealtimeComputation(
       userID: String,
index 801cdab..fbd82cc 100644 (file)
@@ -35,9 +35,9 @@
 
 package gr.grnet.aquarium.charging
 
-import gr.grnet.aquarium.{Aquarium, AquariumInternalError}
+import gr.grnet.aquarium.{Real, Aquarium, AquariumInternalError}
 import gr.grnet.aquarium.computation.{TimeslotComputations, BillingMonthInfo}
-import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
+import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 import gr.grnet.aquarium.message.avro.gen.{EffectivePriceTableMsg, FullPriceTableMsg, ResourceTypeMsg, WalletEntryMsg, ResourceInstanceChargingStateMsg, ResourcesChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.message.avro.{MessageHelpers, AvroHelpers, MessageFactory}
@@ -63,27 +63,6 @@ abstract class ChargingBehaviorSkeleton(
     final val selectorLabelsHierarchy: List[String]
 ) extends ChargingBehavior with Loggable {
 
-  final val HourMillis = CreditsModel.from(1000L * 60 * 60)
-  final val HourMillisInverse = CreditsModel.inv(HourMillis)
-  final val MB = CreditsModel.from(1024L * 1024L)
-  final val MBInverse = CreditsModel.inv(MB)
-  final val GB = CreditsModel.from(1024L * 1024L * 1024L)
-  final val GBInverse = CreditsModel.inv(GB)
-
-  @inline final def HrsOfMillis(timeDeltaMillis: Long): CreditsModel.Type = {
-    CreditsModel.*(
-      HourMillisInverse,
-      CreditsModel.from(timeDeltaMillis)
-    )
-  }
-
-  @inline final def MBsOfBytes(bytes: Double): CreditsModel.Type = {
-    CreditsModel.*(
-      MBInverse,
-      CreditsModel.from(bytes)
-    )
-  }
-
   @inline final protected def rcDebugInfo(rcEvent: ResourceEventMsg) = {
     AvroHelpers.jsonStringOfSpecificRecord(rcEvent)
   }
@@ -99,10 +78,10 @@ abstract class ChargingBehaviorSkeleton(
       DetailsModel.make,
       new JArrayList[ResourceEventMsg](),
       new JArrayList[ResourceEventMsg](),
-      0.0,
-      0.0,
-      0.0,
-      0.0,
+      Real.toMsgField(0.0),
+      Real.toMsgField(0.0),
+      Real.toMsgField(0.0),
+      Real.toMsgField(0.0),
       clientID,
       resource,
       instanceID
@@ -145,14 +124,14 @@ abstract class ChargingBehaviorSkeleton(
       resourceEvent: ResourceEventMsg
   ) {
 
-    resourceInstanceChargingState.setCurrentValue(resourceEvent.getValue.toString.toDouble)
+    resourceInstanceChargingState.setCurrentValue(resourceEvent.getValue)
   }
 
   protected def computeWalletEntriesForNewEvent(
       resourceEvent: ResourceEventMsg,
       resourceType: ResourceTypeMsg,
       billingMonthInfo: BillingMonthInfo,
-      totalCredits: Double,
+      totalCredits: Real,
       referenceStartMillis: Long,
       referenceStopMillis: Long,
       agreementByTimeslot: immutable.SortedMap[Timeslot, UserAgreementModel],
@@ -160,17 +139,17 @@ abstract class ChargingBehaviorSkeleton(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
       aquarium: Aquarium,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
-  ): (Int, Double) = {
+  ): (Int, Real) = {
 
     val userID = resourceEvent.getUserID
     val resourceEventDetails = resourceEvent.getDetails
 
-    var _oldTotalCredits = totalCredits
+    var _oldTotalReal = totalCredits
 
     var _newAccumulatingAmount = computeNewAccumulatingAmount(resourceInstanceChargingState, resourceEventDetails)
     // It will also update the old one inside the data structure.
     resourceInstanceChargingState.setOldAccumulatingAmount(resourceInstanceChargingState.getAccumulatingAmount)
-    resourceInstanceChargingState.setAccumulatingAmount(_newAccumulatingAmount)
+    resourceInstanceChargingState.setAccumulatingAmount(Real.toMsgField(_newAccumulatingAmount))
 
     val policyByTimeslot = aquarium.policyStore.loadSortedPolicyModelsWithin(
       referenceStartMillis,
@@ -204,12 +183,12 @@ abstract class ChargingBehaviorSkeleton(
 
       val (creditsToSubtract, explanation) = this.computeCreditsToSubtract(
         resourceInstanceChargingState,
-        _oldTotalCredits, // FIXME ??? Should recalculate ???
+        _oldTotalReal, // FIXME ??? Should recalculate ???
         timeDeltaMillis,
-        cs.getUnitPrice
+        Real(cs.getUnitPrice)
       )
 
-      cs.setCreditsToSubtract(creditsToSubtract)
+      cs.setCreditsToSubtract(creditsToSubtract.toString())
       cs.setExplanation(explanation)
 
       cs
@@ -219,17 +198,17 @@ abstract class ChargingBehaviorSkeleton(
       throw new AquariumInternalError("No chargeslots computed for resource event %s".format(resourceEvent.getOriginalID))
     }
 
-    val sumOfCreditsToSubtract = fullChargeslots.map(_.getCreditsToSubtract.toDouble).sum
-    val newTotalCredits = _oldTotalCredits - sumOfCreditsToSubtract
+    val sumOfRealToSubtract = fullChargeslots.map(x ⇒ Real(x.getCreditsToSubtract)).sum
+    val newTotalReal = _oldTotalReal - sumOfRealToSubtract
 
     val eventsForWallet = new ju.ArrayList[ResourceEventMsg](resourceInstanceChargingState.getPreviousEvents)
     eventsForWallet.add(0, resourceEvent)
     import scala.collection.JavaConverters.seqAsJavaListConverter
     val newWalletEntry = MessageFactory.newWalletEntryMsg(
       userID,
-      CreditsModel.from(sumOfCreditsToSubtract),
-      CreditsModel.from(_oldTotalCredits),
-      CreditsModel.from(newTotalCredits),
+      Real.toMsgField(sumOfRealToSubtract),
+      Real.toMsgField(_oldTotalReal),
+      Real.toMsgField(newTotalReal),
       TimeHelpers.nowMillis(),
       referenceStartMillis,
       referenceStopMillis,
@@ -246,7 +225,7 @@ abstract class ChargingBehaviorSkeleton(
 
     walletEntryRecorder.apply(newWalletEntry)
 
-    (1, sumOfCreditsToSubtract)
+    (1, sumOfRealToSubtract)
   }
 
 
@@ -257,7 +236,7 @@ abstract class ChargingBehaviorSkeleton(
       currentResourceEvent: ResourceEventMsg,
       referenceStartMillis: Long,
       referenceStopMillis: Long,
-      totalCredits: Double
+      totalCredits: Real
   ): EffectivePriceTableModel = {
 
     val selectorPath = computeSelectorPath(
index bbd2579..1c3b02e 100644 (file)
@@ -43,9 +43,8 @@ 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 gr.grnet.aquarium.{Real, AquariumInternalError, AquariumAwareSkeleton}
 import java.util.{Map ⇒ JMap}
-import gr.grnet.aquarium.event.CreditsModel
 import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 
 /**
@@ -67,7 +66,6 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   def calculateRealtimeUserState(
       userAgreementHistoryModel: UserAgreementHistoryModel,
       userStateMsg: UserStateMsg,
-      billingMonthInfo: BillingMonthInfo,
       resourceMapping: JMap[String, ResourceTypeMsg],
       realtimeMillis: Long
   ) {
@@ -97,10 +95,10 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
             DebugSeq(logger, "virtualEvents", virtualEvents, 1)
 
             processResourceEvents(
+              realtimeMillis,
               virtualEvents,
               userAgreementHistoryModel,
               userStateMsg,
-              billingMonthInfo,
               resourceMapping,
               realtimeMillis
             )
@@ -110,6 +108,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   }
 
   def findOrCalculateWorkingUserStateAtEndOfBillingMonth(
+      processingTimeMillis: Long,
       userAgreementHistoryModel: UserAgreementHistoryModel,
       billingMonthInfo: BillingMonthInfo,
       resourceMapping: JMap[String, ResourceTypeMsg],
@@ -118,6 +117,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
 
     def computeFullMonthBillingAndSaveState(): UserStateMsg = {
       val fullMonthUserState = replayFullMonthBilling(
+        processingTimeMillis,
         userAgreementHistoryModel,
         billingMonthInfo,
         resourceMapping,
@@ -153,7 +153,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       //       First ask if it exists and compute only if not
       val initialUserState0 = MessageFactory.newInitialUserStateMsg(
         userID,
-        CreditsModel.from(0.0),
+        Real.Zero,
         TimeHelpers.nowMillis()
       )
 
@@ -214,37 +214,35 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
    *
    * @param resourceEvent
    * @param userStateMsg
-   * @param billingMonthInfo
    */
   def processResourceEvent(
+      processingTimeMillis: Long,
       resourceEvent: ResourceEventMsg,
       userAgreementHistoryModel: UserAgreementHistoryModel,
       userStateMsg: UserStateMsg,
-      billingMonthInfo: BillingMonthInfo,
-      updateLatestMillis: Boolean,
-      resourceMapping: JMap[String, ResourceTypeMsg]
-  ): Boolean = {
-    logger.warn("processResourceEvent:workingUserState=%s".format(userStateMsg)) //
+      resourceMapping: JMap[String, ResourceTypeMsg],
+      updateLatestMillis: Boolean
+  ) {
+    require(userStateMsg ne null, "userStateMsg ne null")
+
     val resourceName = resourceEvent.getResource
     val resourceTypeMsg = resourceMapping.get(resourceName)
-    if(resourceTypeMsg eq null) {
-      // Unknown (yet) resource, ignoring event.
-      return false
-    }
 
     val chargingBehavior = aquarium.chargingBehaviorOf(resourceTypeMsg)
-    val resourcesChargingState = userStateMsg.getStateOfResources.get(resourceName) match {
-      case null ⇒
-        // First time for this ChargingBehavior.
-        val newState = MessageFactory.newResourcesChargingStateMsg(
-          resourceName,
-          chargingBehavior.initialChargingDetails
-        )
-        userStateMsg.getStateOfResources.put(resourceName, newState)
-        newState
-      case existingState ⇒
-        existingState
-    }
+    val resourcesChargingState = MessageHelpers.getOrInitializeResourcesChargingState(
+      userStateMsg,
+      resourceName,
+      chargingBehavior.initialChargingDetails
+    )
+
+    val eventOccurredMillis = resourceEvent.getOccurredMillis
+    val eventReceivedMillis = resourceEvent.getReceivedMillis
+    val billingMonthInfo = BillingMonthInfo.fromMillis(eventOccurredMillis)
+
+
+    // See if this is out-of-sync
+
+
 
     val m0 = TimeHelpers.nowMillis()
     val (walletEntriesCount, creditsToSubtract) = chargingBehavior.processResourceEvent(
@@ -270,10 +268,10 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   }
 
   def processResourceEvents(
+      processingTimeMillis: Long,
       resourceEvents: Traversable[ResourceEventMsg],
       userAgreementHistoryModel: UserAgreementHistoryModel,
       userStateMsg: UserStateMsg,
-      billingMonthInfo: BillingMonthInfo,
       resourceMapping: JMap[String, ResourceTypeMsg],
       latestUpdateMillis: Long
   ): Unit = {
@@ -281,12 +279,12 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     var _counter = 0
     for(currentResourceEvent ← resourceEvents) {
       processResourceEvent(
+        processingTimeMillis,
         currentResourceEvent,
         userAgreementHistoryModel,
         userStateMsg,
-        billingMonthInfo,
-        false,
-        resourceMapping
+        resourceMapping,
+        false
       )
 
       _counter += 1
@@ -298,6 +296,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   }
 
   def replayFullMonthBilling(
+      processingTimeMillis: Long,
       userAgreementHistoryModel: UserAgreementHistoryModel,
       billingMonthInfo: BillingMonthInfo,
       resourceMapping: JMap[String, ResourceTypeMsg],
@@ -305,6 +304,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
   ): UserStateMsg = {
 
     replayMonthChargingUpTo(
+      processingTimeMillis,
       userAgreementHistoryModel,
       billingMonthInfo,
       billingMonthInfo.monthStopMillis,
@@ -323,6 +323,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
    * @return
    */
   def replayMonthChargingUpTo(
+      processingTimeMillis: Long,
       userAgreementHistoryModel: UserAgreementHistoryModel,
       billingMonthInfo: BillingMonthInfo,
       billingEndTimeMillis: Long,
@@ -336,6 +337,7 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
     // In order to replay the full month, we start with the state at the beginning of the month.
     val previousBillingMonthInfo = billingMonthInfo.previousMonth
     val userStateMsg = findOrCalculateWorkingUserStateAtEndOfBillingMonth(
+      processingTimeMillis,
       userAgreementHistoryModel,
       previousBillingMonthInfo,
       resourceMapping,
@@ -363,12 +365,12 @@ final class ChargingService extends AquariumAwareSkeleton with Lifecycle with Lo
       Debug(logger, "Processing %s", currentResourceEvent)
 
       processResourceEvent(
+        processingTimeMillis,
         currentResourceEvent,
         userAgreementHistoryModel,
         userStateMsg,
-        billingMonthInfo,
-        false,
-        resourceMapping
+        resourceMapping,
+        false
       )
 
       _rcEventsCounter += 1
index 124da45..9a85a7a 100644 (file)
@@ -37,12 +37,15 @@ package gr.grnet.aquarium.charging
 
 import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
-import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
+import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.MessageConstants
 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}
+import gr.grnet.aquarium.Real
+import gr.grnet.aquarium.HrsOfMillis
+import gr.grnet.aquarium.MBsOfBytes
 
 /**
  * In practice a resource usage will be charged for the total amount of usage
@@ -56,16 +59,19 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
 
   def computeCreditsToSubtract(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
-      oldCredits: Double,
+      oldCredits: Real,
       timeDeltaMillis: Long,
-      unitPrice: Double
-  ): (Double /* credits */, String /* explanation */) = {
+      unitPrice: Real
+  ): (Real /* credits */, String /* explanation */) = {
 
-    val oldAccumulatingAmount = resourceInstanceChargingState.getOldAccumulatingAmount
-    val credits = HrsOfMillis(timeDeltaMillis) * oldAccumulatingAmount * unitPrice
+    val bytes = Real(resourceInstanceChargingState.getOldAccumulatingAmount)
+    val MBs = MBsOfBytes(bytes)
+    val Hrs = HrsOfMillis(timeDeltaMillis)
+
+    val credits = Hrs * MBs * unitPrice
     val explanation = "Hours(%s) * MBs(%s) * UnitPrice(%s)".format(
-      HrsOfMillis(timeDeltaMillis),
-      MBsOfBytes(oldAccumulatingAmount),
+      Hrs,
+      MBs,
       unitPrice
     )
 
@@ -78,7 +84,7 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       currentResourceEvent: ResourceEventMsg,
       referenceStartMillis: Long,
       referenceStopMillis: Long,
-      totalCredits: Double
+      totalCredits: Real
   ): List[String] = {
     List(MessageConstants.DefaultSelectorKey)
   }
@@ -92,10 +98,10 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       eventDetails: DetailsModel.Type
   ) = {
 
-    val oldAccumulatingAmount = CreditsModel.from(resourceInstanceChargingState.getOldAccumulatingAmount)
-    val currentValue = CreditsModel.from(resourceInstanceChargingState.getCurrentValue)
+    val oldAccumulatingAmount = Real(resourceInstanceChargingState.getOldAccumulatingAmount)
+    val currentValue = Real(resourceInstanceChargingState.getCurrentValue)
 
-    CreditsModel.add(oldAccumulatingAmount, currentValue)
+    oldAccumulatingAmount + currentValue
   }
 
   def constructImplicitEndEventFor(resourceEvent: ResourceEventMsg, newOccurredMillis: Long) = {
@@ -120,7 +126,7 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
        userAgreementHistoryModel: UserAgreementHistoryModel,
        userStateMsg: UserStateMsg,
        walletEntryRecorder: WalletEntryMsg ⇒ Unit
-   ): (Int, CreditsModel.Type) = {
+   ): (Int, Real) = {
 
     // 1. Ensure proper initial state per resource and per instance
     ensureInitializedWorkingState(resourcesChargingState, resourceEvent)
@@ -168,7 +174,7 @@ final class ContinuousChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       resourceEvent,
       resourceType,
       billingMonthInfo,
-      userStateMsg.getTotalCredits,
+      Real(userStateMsg.getTotalCredits),
       previousEvent.getOccurredMillis,
       resourceEvent.getOccurredMillis,
       userAgreementHistoryModel.agreementByTimeslot,
index c392d13..6c62e6a 100644 (file)
 
 package gr.grnet.aquarium.charging
 
-import gr.grnet.aquarium.Aquarium
+import gr.grnet.aquarium.{Real, Aquarium}
 import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
-import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
+import gr.grnet.aquarium.event.DetailsModel
 import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
 import gr.grnet.aquarium.message.MessageConstants
 
@@ -52,15 +52,15 @@ import gr.grnet.aquarium.message.MessageConstants
 final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
   def computeCreditsToSubtract(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
-      oldCredits: CreditsModel.Type,
+      oldCredits: Real,
       timeDeltaMillis: Long,
-      unitPrice: CreditsModel.Type
-  ): (CreditsModel.Type, String /* explanation */) = {
+      unitPrice: Real
+  ): (Real, String /* explanation */) = {
 
-    val currentValue = CreditsModel.from(resourceInstanceChargingState.getCurrentValue)
+    val currentValue = Real(resourceInstanceChargingState.getCurrentValue)
     // Always remember to multiply with the `unitPrice`, since it scales the credits, depending on
     // the particular resource type tha applies.
-    val credits = CreditsModel.mul(currentValue, unitPrice)
+    val credits = currentValue * unitPrice
     val explanation = "Value(%s) * UnitPrice(%s)".format(currentValue, unitPrice)
 
     (credits, explanation)
@@ -72,7 +72,7 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       currentResourceEvent: ResourceEventMsg,
       referenceFromMillis: Long,
       referenceToMillis: Long,
-      totalCredits: CreditsModel.Type
+      totalCredits: Real
   ): List[String] = {
     List(MessageConstants.DefaultSelectorKey)
   }
@@ -86,7 +86,7 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       userAgreementHistoryModel: UserAgreementHistoryModel,
       userStateMsg: UserStateMsg,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
-  ): (Int, Double) = {
+  ): (Int, Real) = {
     // The credits are given in the value
     // But we cannot just apply them, since we also need to take into account the unit price.
     // Normally, the unit price is 1.0 but we have the flexibility to allow more stuff).
@@ -105,7 +105,7 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
       resourceEvent,
       resourceType,
       billingMonthInfo,
-      userStateMsg.getTotalCredits,
+      Real(userStateMsg.getTotalCredits),
       resourceEvent.getOccurredMillis,
       resourceEvent.getOccurredMillis + 1, // single point in time
       userAgreementHistoryModel.agreementByTimeslot,
@@ -123,8 +123,8 @@ final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
   def computeNewAccumulatingAmount(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
       eventDetails: DetailsModel.Type
-  ): CreditsModel.Type = {
-    CreditsModel.from(resourceInstanceChargingState.getOldAccumulatingAmount)
+  ): Real = {
+    Real(resourceInstanceChargingState.getOldAccumulatingAmount)
   }
 
   def createVirtualEventsForRealtimeComputation(
index a697b51..7cf2f27 100644 (file)
@@ -39,7 +39,6 @@ import VMChargingBehavior.SelectorLabels.PowerStatus
 import VMChargingBehavior.Selectors.Power
 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.{UserStateMsg, WalletEntryMsg, ResourceTypeMsg, ResourcesChargingStateMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
@@ -47,6 +46,8 @@ import gr.grnet.aquarium.message.avro.{AvroHelpers, MessageHelpers, MessageFacto
 import gr.grnet.aquarium.util.LogHelpers._
 import gr.grnet.aquarium.{Aquarium, AquariumInternalError}
 import scala.collection.JavaConverters.asScalaBufferConverter
+import gr.grnet.aquarium.Real
+import gr.grnet.aquarium.HrsOfMillis
 
 /**
  * The new [[gr.grnet.aquarium.charging.ChargingBehavior]] for VMs usage.
@@ -56,10 +57,10 @@ import scala.collection.JavaConverters.asScalaBufferConverter
 final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus)) {
   def computeCreditsToSubtract(
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
-      oldCredits: CreditsModel.Type,
+      oldCredits: Real,
       timeDeltaMillis: Long,
-      unitPrice: Double
-  ): (CreditsModel.Type, String /* explanation */) = {
+      unitPrice: Real
+  ): (Real, String /* explanation */) = {
 
     val credits = HrsOfMillis(timeDeltaMillis) * unitPrice
     val explanation = "Hours(%s) * UnitPrice(%s)".format(HrsOfMillis(timeDeltaMillis), unitPrice)
@@ -74,7 +75,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
       currentResourceEvent: ResourceEventMsg,
       referenceFromMillis: Long,
       referenceToMillis: Long,
-      totalCredits: CreditsModel.Type
+      totalCredits: Real
   ): List[String] = {
     val previousEvents = resourceInstanceChargingState.getPreviousEvents.asScala.toList
     (currentResourceEvent.getValue.toInt,previousEvents) match {
@@ -105,7 +106,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
       eventDetails: DetailsModel.Type
   ) = {
-    CreditsModel.from(resourceInstanceChargingState.getCurrentValue)
+    Real(resourceInstanceChargingState.getCurrentValue)
   }
 
   def constructImplicitEndEventFor(resourceEvent: ResourceEventMsg, newOccurredMillis: Long) = {
@@ -119,7 +120,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
       setDetails(newDetails).
       setOccurredMillis(newOccurredMillis).
       setReceivedMillis(newOccurredMillis).
-      setValue(VMChargingBehaviorValues.OFF.toString).
+      setValue(VMChargingBehaviorValues.OFF).
       build()
   }
 
@@ -140,7 +141,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
       userAgreementHistoryModel: UserAgreementHistoryModel,
       userStateMsg: UserStateMsg,
       walletEntryRecorder: WalletEntryMsg ⇒ Unit
-  ): (Int, CreditsModel.Type) = {
+  ): (Int, Real) = {
 
     // 1. Ensure proper initial state per resource and per instance
     ensureInitializedWorkingState(resourcesChargingState,resourceEvent)
@@ -155,7 +156,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
     val previousEvents = resourceInstanceChargingState.getPreviousEvents
     val retVal = previousEvents.size() match {
       case 0 ⇒
-        (0,0.0D)
+        (0, Real.Zero)
 
       case _ ⇒
         val previousEvent = previousEvents.get(0) // head is most recent
@@ -165,7 +166,7 @@ final class VMChargingBehavior extends ChargingBehaviorSkeleton(List(PowerStatus
           resourceEvent,
           resourceType,
           billingMonthInfo,
-          userStateMsg.getTotalCredits,
+          Real(userStateMsg.getTotalCredits),
           previousEvent.getOccurredMillis,
           resourceEvent.getOccurredMillis,
           userAgreementHistoryModel.agreementByTimeslot,
index 2ccfa0b..474c7cd 100644 (file)
@@ -42,7 +42,7 @@ import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 import gr.grnet.aquarium.message.avro.{AvroHelpers, MessageHelpers}
 import gr.grnet.aquarium.message.avro.gen._
 import gr.grnet.aquarium.util.json.JsonSupport
-import gr.grnet.aquarium.{Aquarium, ResourceLocator, AquariumBuilder}
+import gr.grnet.aquarium.{Real, Aquarium, ResourceLocator, AquariumBuilder}
 import java.io.File
 import java.util.concurrent.atomic.AtomicLong
 import scala.collection.immutable.TreeMap
@@ -210,12 +210,12 @@ object BillEntryMsg {
   }
 
 
-  private[this] def toChargeEntry(c:ChargeslotMsg) : (ChargeEntryMsg,Long,Double) = {
+  private[this] def toChargeEntry(c:ChargeslotMsg) : (ChargeEntryMsg,Long,Real) = {
     val unitPrice = c.getUnitPrice.toString
     val startTime = c.getStartMillis.toString
     val endTime   = c.getStopMillis.toString
     val difTime   = (c.getStopMillis - c.getStartMillis).toLong
-    val unitsD     = (c.getCreditsToSubtract/c.getUnitPrice)
+    val unitsD     = (Real(c.getCreditsToSubtract)/Real(c.getUnitPrice))
     val credits   = c.getCreditsToSubtract.toString
     (newChargeEntry(counter.getAndIncrement.toString,unitPrice,
                     startTime,endTime,difTime.toString,unitsD.toString,credits),difTime,unitsD)
@@ -223,7 +223,7 @@ object BillEntryMsg {
 
 
 
-  private[this] def toEventEntry(eventType:String,c:ChargeslotMsg) : (EventEntryMsg,Long,Double) = {
+  private[this] def toEventEntry(eventType:String,c:ChargeslotMsg) : (EventEntryMsg,Long,Real) = {
     val (c1,l1,d1) = toChargeEntry(c)
     (newEventEntry(eventType,javaList(c1)),l1,d1)
   }
@@ -266,7 +266,7 @@ object BillEntryMsg {
     ///FIXME: val elapsedTime = w.getChargeslots.asScala.foldLeft()
    //c.getStopMillis - c.getStartMillis
     var totalElapsedTime = 0L
-    var totalUnits = 0.0D
+    var totalUnits = Real.Zero
     val eventEntry = new java.util.ArrayList[EventEntryMsg]() //new ListBuffer[EventEntry]
       for { c <- w.getChargeslots.asScala }{
         if(c.getCreditsToSubtract != 0.0) {
index d107f5e..7327d6e 100644 (file)
@@ -36,7 +36,7 @@
 package gr.grnet.aquarium.charging.state
 
 import gr.grnet.aquarium.policy.UserAgreementModel
-import gr.grnet.aquarium.event.CreditsModel
+import gr.grnet.aquarium.Real
 
 /**
  * This is used to bootstrap the [[gr.grnet.aquarium.charging.state.UserStateModel]].
@@ -46,7 +46,7 @@ import gr.grnet.aquarium.event.CreditsModel
 
 final case class UserStateBootstrap(
     initialAgreement: UserAgreementModel,
-    initialCredits: CreditsModel.Type
+    initialCredits: Real
 ) {
   def userID = initialAgreement.msg.getUserID
 
index ae86d7e..ff8c25d 100644 (file)
@@ -36,8 +36,7 @@
 package gr.grnet.aquarium.charging.state
 
 import gr.grnet.aquarium.message.avro.gen.UserStateMsg
-import gr.grnet.aquarium.util.json.JsonSupport
-import gr.grnet.aquarium.event.CreditsModel
+import gr.grnet.aquarium.Real
 
 /**
  *
@@ -53,8 +52,8 @@ final class UserStateModel(msg: UserStateMsg) {
 
   def latestResourceEventOccurredMillis = this.msg.getLatestResourceEventOccurredMillis
 
-  @inline final def totalCredits: CreditsModel.Type = {
-    CreditsModel.from(msg.getTotalCredits)
+  @inline final def totalCredits: Real = {
+    Real(msg.getTotalCredits)
   }
 
   override def toString = msg.toString
index 5bcbeff..1601c14 100644 (file)
@@ -85,7 +85,7 @@ object TimeslotComputations extends Loggable {
       agreement: UserAgreementModel,
       fullPriceTableModelGetter: (UserAgreementModel, PolicyModel) ⇒ FullPriceTableModel,
       effectivePriceTableModelSelector: FullPriceTableModel ⇒ EffectivePriceTableModel
-  ): SortedMap[Timeslot, Double] = {
+  ): SortedMap[Timeslot, String] = {
 
     // Note that most of the code is taken from calcChangeChunks()
     val ret = resolveEffectiveUnitPricesForTimeslot(
diff --git a/src/main/scala/gr/grnet/aquarium/event/CreditsModel.scala b/src/main/scala/gr/grnet/aquarium/event/CreditsModel.scala
deleted file mode 100644 (file)
index 33577bb..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- *   1. Redistributions of source code must retain the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer in the documentation and/or other materials
- *      provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- */
-
-package gr.grnet.aquarium.event
-
-//trait CreditsModel {
-//  /**
-//   * The type of credits
-//   */
-//  type Type
-//
-//  def fromString(s: CharSequence): Type
-//
-//  def toString(credits: Type): CharSequence
-//
-//  def fromDouble(d: Double): Type
-//
-//  def toDouble(credits: Type): Double
-//}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>
- */
-object CreditsModel {
-  type Type = Double // A nice value type would be great here.
-  type TypeInMessage = Double
-
-  @inline final def from(s: String): Type = s.toString.toDouble
-
-  @inline final def from(d: TypeInMessage): Type = d
-
-  @inline final def from(l: Long): Type = l.toDouble
-
-  @inline final def toString(t: Type): String = t.toString
-
-  @inline final def toTypeInMessage(t: Type): TypeInMessage = t
-
-  @inline final def mul(a: Type, b: Type): Type = a * b
-
-  @inline final def *(a: Type, b: Type): Type = a * b
-
-  @inline final def div(a: Type, b: Type): Type = a / b
-
-  @inline final def /(a: Type, b: Type): Type = a / b
-
-  @inline final def add(a: Type, b: Type): Type = a + b
-
-  @inline final def +(a: Type, b: Type): Type = a + b
-
-  @inline final def sub(a: Type, b: Type): Type = a - b
-
-  @inline final def -(a: Type, b: Type): Type = a - b
-
-  @inline final def neg(a: Type): Type = -a
-
-  @inline final def inv(a: Type): Type = 1 / a
-}
index 2c6bb3a..9d34fef 100644 (file)
 
 package gr.grnet.aquarium.message.avro
 
-import gr.grnet.aquarium.charging.state.UserStateBootstrap
 import gr.grnet.aquarium.computation.BillingMonthInfo
-import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
+import gr.grnet.aquarium.event.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
 import gr.grnet.aquarium.policy.ResourceType
-import gr.grnet.aquarium.charging.state.UserStateBootstrap
 import gr.grnet.aquarium.util.date.TimeHelpers
-
+import gr.grnet.aquarium.Real
 
 /**
  * Provides helper methods that construct avro messages.
@@ -68,19 +63,32 @@ object MessageFactory {
     av
   }
 
-  def anyValueMsgOfList(l: JArrayList[AnyValueMsg]) = {
+  def anyValueMsgOfList(l: java.util.List[AnyValueMsg]) = {
     val av = new AnyValueMsg
     av.setAnyValue(l)
     av
   }
 
-  def newEffectiveUnitPriceMsg(unitPrice: Double, whenOpt: Option[CronSpecTupleMsg] = None) = {
+  def newEffectiveUnitPriceMsg(
+      unitPrice: String,
+      whenOpt: Option[CronSpecTupleMsg]
+  ): EffectiveUnitPriceMsg = {
     EffectiveUnitPriceMsg.newBuilder().
       setUnitPrice(unitPrice).
       setWhen(whenOpt.getOrElse(null)).
     build()
   }
 
+  def newEffectiveUnitPriceMsg(
+      unitPrice: Double,
+      whenOpt: Option[CronSpecTupleMsg]
+  ): EffectiveUnitPriceMsg = {
+    newEffectiveUnitPriceMsg(unitPrice.toString, whenOpt)
+  }
+
+  def newJList[T]   = new java.util.ArrayList[T]()
+  def newJMap[K, V] = new java.util.HashMap[K, V]()
+
   def newEffectivePriceTableMsg(priceOverrides: EffectiveUnitPriceMsg*) = {
     EffectivePriceTableMsg.newBuilder().
       setPriceOverrides(priceOverrides.asJava).
@@ -220,25 +228,25 @@ object MessageFactory {
 
   def newWalletEntryMsg(
       userID: String,
-      sumOfCreditsToSubtract: CreditsModel.Type,
-      oldTotalCredits: CreditsModel.Type,
-      newTotalCredits: CreditsModel.Type,
+      sumOfCreditsToSubtract: String,
+      oldTotalCredits: String,
+      newTotalCredits: String,
       whenComputedMillis: Long,
       referenceStartMillis: Long,
       referenceStopMillis: Long,
       billingYear: Int,
       billingMonth: Int,
       billingMonthDay: Int,
-      chargeslots: ju.List[ChargeslotMsg],
-      resourceEvents: ju.List[ResourceEventMsg],
+      chargeslots: java.util.List[ChargeslotMsg],
+      resourceEvents: java.util.List[ResourceEventMsg],
       resourceType: ResourceTypeMsg,
       isSynthetic: Boolean
   ): WalletEntryMsg = {
     WalletEntryMsg.newBuilder().
       setUserID(userID).
-      setSumOfCreditsToSubtract(CreditsModel.toTypeInMessage(sumOfCreditsToSubtract)).
-      setOldTotalCredits(CreditsModel.toTypeInMessage(oldTotalCredits)).
-      setNewTotalCredits(CreditsModel.toTypeInMessage(newTotalCredits)).
+      setSumOfCreditsToSubtract(sumOfCreditsToSubtract).
+      setOldTotalCredits(oldTotalCredits).
+      setNewTotalCredits(newTotalCredits).
       setWhenComputedMillis(whenComputedMillis).
       setReferenceStartMillis(referenceStartMillis).
       setReferenceStopMillis(referenceStopMillis).
@@ -254,12 +262,12 @@ object MessageFactory {
 
   def newResourceInstanceChargingStateMsg(
       details: DetailsModel.Type,
-      previousEvents: ju.List[ResourceEventMsg],
-      implicitlyIssuedStartEvents: ju.List[ResourceEventMsg],
-      oldAccumulatingAmount: Double,
-      accumulatingAmount: Double,
-      previousValue: Double,
-      currentValue: Double,
+      previousEvents: java.util.List[ResourceEventMsg],
+      implicitlyIssuedStartEvents: java.util.List[ResourceEventMsg],
+      oldAccumulatingAmount: String,
+      accumulatingAmount: String,
+      previousValue: String,
+      currentValue: String,
       clientID: String,
       resource: String,
       instanceID: String
@@ -269,10 +277,10 @@ object MessageFactory {
     msg.setDetails(details)
     msg.setPreviousEvents(previousEvents)
     msg.setImplicitlyIssuedStartEvents(implicitlyIssuedStartEvents)
-    msg.setOldAccumulatingAmount(java.lang.Double.valueOf(oldAccumulatingAmount))
-    msg.setAccumulatingAmount(java.lang.Double.valueOf(accumulatingAmount))
-    msg.setPreviousValue(java.lang.Double.valueOf(previousValue))
-    msg.setCurrentValue(java.lang.Double.valueOf(currentValue))
+    msg.setOldAccumulatingAmount(oldAccumulatingAmount)
+    msg.setAccumulatingAmount(accumulatingAmount)
+    msg.setPreviousValue(previousValue)
+    msg.setCurrentValue(currentValue)
     msg.setClientID(clientID)
     msg.setResource(resource)
     msg.setInstanceID(instanceID)
@@ -286,13 +294,13 @@ object MessageFactory {
     val msg = new ResourcesChargingStateMsg
     msg.setResource(resourceName)
     msg.setDetails(initialChargingDetails)
-    msg.setStateOfResourceInstance(new JHashMap())
+    msg.setStateOfResourceInstance(newJMap)
     msg
   }
 
   def newEmptyUserAgreementHistoryMsg() = {
     val msg = new UserAgreementHistoryMsg
-    msg.setAgreements(new ju.ArrayList[UserAgreementMsg]())
+    msg.setAgreements(newJList[UserAgreementMsg])
     msg
   }
 
@@ -333,7 +341,7 @@ object MessageFactory {
     msg
   }
 
-  def newWalletEntriesMsg(entries: ju.List[WalletEntryMsg] = new ju.ArrayList[WalletEntryMsg]()) = {
+  def newWalletEntriesMsg(entries: java.util.List[WalletEntryMsg] = newJList[WalletEntryMsg]) = {
     val msg = new WalletEntriesMsg
     msg.setEntries(entries)
     msg
@@ -346,15 +354,15 @@ object MessageFactory {
       setParentID(null).
       setValidFromMillis(millis).
       setValidToMillis(Long.MaxValue).
-      setChargingBehaviors(new ju.ArrayList[String]()).
-      setResourceMapping(new JHashMap()).
-      setRoleMapping(new ju.HashMap[String, FullPriceTableMsg]()).
+      setChargingBehaviors(newJList).
+      setResourceMapping(newJMap).
+      setRoleMapping(newJMap).
       build()
   }
 
   def newInitialUserStateMsg(
       userID: String,
-      initialCredits: CreditsModel.Type,
+      initialCredits: Real,
       occurredMillis: Long,
       originalID: String = MessageHelpers.UserStateMsgIDGenerator.nextUID()
   ): UserStateMsg = {
@@ -367,7 +375,7 @@ object MessageFactory {
     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(initialCredits)))
+    msg.setTotalCredits(Real.toMsgField(initialCredits))
     msg.setLatestUpdateMillis(java.lang.Long.valueOf(occurredMillis))
     msg.setInStoreID(null)
     msg.setOriginalID(originalID)
index ffa3525..67f2431 100644 (file)
 
 package gr.grnet.aquarium.message.avro
 
-import gr.grnet.aquarium.AquariumInternalError
-import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
+import gr.grnet.aquarium.{Real, AquariumInternalError}
+import gr.grnet.aquarium.event.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}
+import gr.grnet.aquarium.message.avro.gen.{ResourcesChargingStateMsg, UserAgreementMsg, UserAgreementHistoryMsg, AnyValueMsg, WalletEntryMsg, EffectivePriceTableMsg, FullPriceTableMsg, ResourceInstanceChargingStateMsg, UserStateMsg, IMEventMsg, ResourceEventMsg}
 import gr.grnet.aquarium.policy.EffectivePriceTableModel
 import gr.grnet.aquarium.uid.UUIDGenerator
 import gr.grnet.aquarium.util.LogHelpers.Debug
@@ -345,12 +345,30 @@ final object MessageHelpers {
     }
   }
 
-  def subtractCredits(msg: UserStateMsg, credits: CreditsModel.Type) {
-    val oldTotal = CreditsModel.from(msg.getTotalCredits)
-    val newTotal = CreditsModel.-(oldTotal, credits)
-    msg.setTotalCredits(CreditsModel.toTypeInMessage(newTotal))
+  def subtractCredits(msg: UserStateMsg, credits: Real) {
+    val oldTotal = Real(msg.getTotalCredits)
+    val newTotal = oldTotal - credits
+    msg.setTotalCredits(Real.toMsgField(newTotal))
   }
 
+  def getOrInitializeResourcesChargingState(
+      userStateMsg: UserStateMsg,
+      resourceName: String,
+      initialChargingDetails: DetailsModel.Type
+  ): ResourcesChargingStateMsg = {
+    userStateMsg.getStateOfResources.get(resourceName) match {
+      case null ⇒
+        // First time for this ChargingBehavior.
+        val newState = MessageFactory.newResourcesChargingStateMsg(
+          resourceName,
+          initialChargingDetails
+        )
+        userStateMsg.getStateOfResources.put(resourceName, newState)
+        newState
+      case existingState ⇒
+        existingState
+    }
+  }
 
 
   //  final def splitEffectiveUnitPriceTimeslot(
diff --git a/src/main/scala/gr/grnet/aquarium/package.scala b/src/main/scala/gr/grnet/aquarium/package.scala
new file mode 100644 (file)
index 0000000..04c9b71
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *
+ *  * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *  *
+ *  * Redistribution and use in source and binary forms, with or
+ *  * without modification, are permitted provided that the following
+ *  * conditions are met:
+ *  *
+ *  *   1. Redistributions of source code must retain the above
+ *  *      copyright notice, this list of conditions and the following
+ *  *      disclaimer.
+ *  *
+ *  *   2. Redistributions in binary form must reproduce the above
+ *  *      copyright notice, this list of conditions and the following
+ *  *      disclaimer in the documentation and/or other materials
+ *  *      provided with the distribution.
+ *  *
+ *  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ *  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ *  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ *  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ *  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  * POSSIBILITY OF SUCH DAMAGE.
+ *  *
+ *  * The views and conclusions contained in the software and
+ *  * documentation are those of the authors and should not be
+ *  * interpreted as representing official policies, either expressed
+ *  * or implied, of GRNET S.A.
+ *
+ */
+
+package gr.grnet
+
+/**
+ *
+ * @author Christos KK Loverdos <loverdos@gmail.com>
+ */
+package object aquarium {
+  final type Real = BigDecimal
+
+  @inline final def HrsOfMillis(timeDeltaMillis: Long): Real = {
+    Real.HourMillisInverse * timeDeltaMillis
+  }
+
+  @inline final def MBsOfBytes(bytes: Double): Real = {
+    Real.MBInverse * bytes
+  }
+
+  @inline final def MBsOfBytes(bytes: Real): Real = {
+    Real.MBInverse * bytes
+  }
+
+  @inline final def GBsOfBytes(bytes: Double): Real = {
+    Real.GBInverse * bytes
+  }
+
+}
index 7f2a2ab..06ce57e 100644 (file)
@@ -45,7 +45,7 @@ import collection.mutable
  */
 
 case class EffectiveUnitPriceModel(
-    unitPrice: Double,
+    unitPrice: String,
     when: Option[(CronSpec, CronSpec)] = None
 ) {
 
index f708bd5..17a5cc6 100644 (file)
@@ -157,8 +157,8 @@ final class AkkaService extends AquariumAwareSkeleton with Configurable with Lif
   }
 
   def notifyUserActorPostStop(userActor: UserActor): Unit = {
-    logger.debug("Removing UserActor %s from stopping set (after postStop())".format(userActor.unsafeUserID))
-    this.stoppingUserActors.remove(userActor.unsafeUserID)
+    logger.debug("Removing UserActor %s from stopping set (after postStop())".format(userActor.userID))
+    this.stoppingUserActors.remove(userActor.userID)
   }
 
   private[this] def gracefullyStopUserActor(userID: String, actorRef: ActorRef): Unit = {
@@ -174,7 +174,7 @@ final class AkkaService extends AquariumAwareSkeleton with Configurable with Lif
       return
     }
 
-    val userID = userActor.unsafeUserID
+    val userID = userActor.userID
     val actorRef = userActor.self
 
     this._userActorCache.invalidate(userID)