42ea2b5ea10b070c647dc4edb16ef41579706f06
[aquarium] / src / main / scala / gr / grnet / aquarium / message / avro / MessageFactory.scala
1 /*
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35
36 package gr.grnet.aquarium.message.avro
37
38 import gr.grnet.aquarium.charging.state.UserStateBootstrap
39 import gr.grnet.aquarium.computation.BillingMonthInfo
40 import gr.grnet.aquarium.event.{CreditsModel, DetailsModel}
41 import gr.grnet.aquarium.message.avro.gen._
42 import java.{util ⇒ ju}
43 import java.util.{ArrayList ⇒ JArrayList}
44 import scala.collection.JavaConverters.mapAsJavaMapConverter
45 import scala.collection.JavaConverters.seqAsJavaListConverter
46 import scala.Predef.Map
47 import gr.grnet.aquarium.policy.ResourceType
48 import gr.grnet.aquarium.charging.state.UserStateBootstrap
49 import gr.grnet.aquarium.util.date.TimeHelpers
50
51
52 /**
53  * Provides helper methods that construct avro messages.
54  *
55  * @author Christos KK Loverdos <loverdos@gmail.com>
56  */
57 object MessageFactory {
58   def anyValueMsgOfBoolean(x: Boolean) = {
59     val av = new AnyValueMsg
60     av.setAnyValue(java.lang.Boolean.valueOf(x))
61     av
62   }
63
64   def anyValueMsgOfString(x: String) = {
65     val av = new AnyValueMsg
66     av.setAnyValue(x)
67     av
68   }
69
70   def anyValueMsgOfList(l: JArrayList[AnyValueMsg]) = {
71     val av = new AnyValueMsg
72     av.setAnyValue(l)
73     av
74   }
75
76   def newEffectiveUnitPriceMsg(unitPrice: Double, whenOpt: Option[CronSpecTupleMsg] = None) = {
77     EffectiveUnitPriceMsg.newBuilder().
78       setUnitPrice(unitPrice).
79       setWhen(whenOpt.getOrElse(null)).
80     build()
81   }
82
83   def newEffectivePriceTableMsg(priceOverrides: EffectiveUnitPriceMsg*) = {
84     EffectivePriceTableMsg.newBuilder().
85       setPriceOverrides(priceOverrides.asJava).
86     build()
87   }
88
89   def newSelectorValueMsg(ept: EffectivePriceTableMsg): SelectorValueMsg = {
90     SelectorValueMsg.newBuilder().
91       setSelectorValue(ept).
92     build()
93   }
94
95   def newSelectorValueMsg(map: Map[String, SelectorValueMsg]): SelectorValueMsg = {
96     SelectorValueMsg.newBuilder().
97       setSelectorValue(map.asJava).
98     build()
99   }
100
101   def newSelectorValueMsg(pairs: (String, SelectorValueMsg)*): SelectorValueMsg = {
102     SelectorValueMsg.newBuilder().
103       setSelectorValue(Map(pairs:_*).asJava).
104     build()
105   }
106
107   def newFullPriceTableMsg(perResource: (String, Map[String, SelectorValueMsg])*) = {
108     FullPriceTableMsg.newBuilder().
109       setPerResource(
110         Map((for((k, v) ← perResource) yield (k, v.asJava)):_*).asJava
111       ).
112     build()
113   }
114
115   def newRoleMappingMsg(map: Map[String, FullPriceTableMsg]): java.util.Map[String, FullPriceTableMsg] = {
116     map.asJava
117   }
118
119   def newRoleMappingMsg(pairs: (String, FullPriceTableMsg)*): java.util.Map[String, FullPriceTableMsg] = {
120     Map(pairs:_*).asJava
121   }
122
123   def newResourceTypeMsg(name: String, unit: String, chargingBehavior: String) = {
124     ResourceTypeMsg.newBuilder().
125       setName(name).
126       setUnit(unit).
127       setChargingBehaviorClass(chargingBehavior).
128     build()
129   }
130
131   def newResourceTypeMsg(model: ResourceType): ResourceTypeMsg = {
132     newResourceTypeMsg(model.name, model.unit, model.chargingBehavior)
133   }
134
135   def newResourceTypeMsgs(rts: ResourceTypeMsg*) = {
136     rts.asJava
137   }
138
139 //  def newResourceTypeMsgsMap(rts: ResourceTypeMsg*): java.util.Map[String, ResourceTypeMsg] = {
140 //    rts.map(rt ⇒ (rt.getName, rt)).toMap.asJava
141 //  }
142
143   def newResourceTypeMsgsMap(resourceTypes: Map[String, ResourceType]): java.util.Map[String, ResourceTypeMsg] = {
144     resourceTypes.map(rtt ⇒ (rtt._1, newResourceTypeMsg(rtt._2))).asJava
145   }
146
147   def newChargingBehaviorMsgs(cbs: String*) = {
148     cbs.asJava
149   }
150
151   def newBooleanDetail(name: String, value: Boolean) = {
152     (name, anyValueMsgOfBoolean(value))
153   }
154
155   def newStringDetail(name: String, value: String) = {
156     (name, anyValueMsgOfString(value))
157   }
158
159   def newDetails(details: (String, AnyValueMsg)*): DetailsModel.Type = {
160     DetailsModel.fromScalaTuples(details:_*)
161   }
162
163   def newResourceEventMsg(
164       originalID: String,
165       occurredMillis: Long,
166       receivedMillis: Long,
167       userID: String,
168       clientID: String,
169       resource: String,
170       instanceID: String,
171       value: String,
172       eventVersion: String,
173       details: DetailsModel.Type = newDetails(),
174       inStoreID: String = null
175   ) = {
176     ResourceEventMsg.newBuilder().
177       setOriginalID(originalID).
178       setOccurredMillis(occurredMillis).
179       setReceivedMillis(receivedMillis).
180       setUserID(userID).
181       setClientID(clientID).
182       setResource(resource).
183       setInstanceID(instanceID).
184       setValue(value).
185       setEventVersion(eventVersion).
186       setDetails(details).
187       setInStoreID(inStoreID).
188     build()
189   }
190
191   def newIMEventMsg(
192       originalID: String,
193       occurredMillis: Long,
194       receivedMillis: Long,
195       userID: String,
196       clientID: String,
197       isActive: Boolean,
198       role: String,
199       eventVersion: String,
200       eventType: String,
201       details: DetailsModel.Type = newDetails(),
202       inStoreID: String = null
203   ) = {
204     IMEventMsg.newBuilder().
205       setOriginalID(originalID).
206       setInStoreID(null).
207       setOccurredMillis(occurredMillis).
208       setReceivedMillis(receivedMillis).
209       setUserID(userID).
210       setClientID(clientID).
211       setIsActive(isActive).
212       setRole(role).
213       setEventVersion(eventVersion).
214       setEventType(eventType).
215       setDetails(details).
216       setInStoreID(inStoreID).
217     build()
218   }
219
220   def newWalletEntryMsg(
221       userID: String,
222       sumOfCreditsToSubtract: CreditsModel.Type,
223       oldTotalCredits: CreditsModel.Type,
224       newTotalCredits: CreditsModel.Type,
225       whenComputedMillis: Long,
226       referenceStartMillis: Long,
227       referenceStopMillis: Long,
228       billingYear: Int,
229       billingMonth: Int,
230       billingMonthDay: Int,
231       chargeslots: ju.List[ChargeslotMsg],
232       resourceEvents: ju.List[ResourceEventMsg],
233       resourceType: ResourceTypeMsg,
234       isSynthetic: Boolean
235   ): WalletEntryMsg = {
236     WalletEntryMsg.newBuilder().
237       setUserID(userID).
238       setSumOfCreditsToSubtract(CreditsModel.toTypeInMessage(sumOfCreditsToSubtract)).
239       setOldTotalCredits(CreditsModel.toTypeInMessage(oldTotalCredits)).
240       setNewTotalCredits(CreditsModel.toTypeInMessage(newTotalCredits)).
241       setWhenComputedMillis(whenComputedMillis).
242       setReferenceStartMillis(referenceStartMillis).
243       setReferenceStopMillis(referenceStopMillis).
244       setBillingYear(billingYear).
245       setBillingMonth(billingMonth).
246       setBillingMonthDay(billingMonthDay).
247       setChargeslots(chargeslots).
248       setResourceEvents(resourceEvents).
249       setResourceType(resourceType).
250       setIsSynthetic(isSynthetic).
251     build()
252   }
253
254   def newResourceInstanceChargingStateMsg(
255       details: DetailsModel.Type,
256       previousEvents: ju.List[ResourceEventMsg],
257       implicitlyIssuedStartEvents: ju.List[ResourceEventMsg],
258       oldAccumulatingAmount: Double,
259       accumulatingAmount: Double,
260       previousValue: Double,
261       currentValue: Double,
262       clientID: String,
263       resource: String,
264       instanceID: String
265   ): ResourceInstanceChargingStateMsg = {
266
267     val msg = new ResourceInstanceChargingStateMsg
268     msg.setDetails(details)
269     msg.setPreviousEvents(previousEvents)
270     msg.setImplicitlyIssuedStartEvents(implicitlyIssuedStartEvents)
271     msg.setOldAccumulatingAmount(java.lang.Double.valueOf(oldAccumulatingAmount))
272     msg.setAccumulatingAmount(java.lang.Double.valueOf(accumulatingAmount))
273     msg.setPreviousValue(java.lang.Double.valueOf(previousValue))
274     msg.setCurrentValue(java.lang.Double.valueOf(currentValue))
275     msg.setClientID(clientID)
276     msg.setResource(resource)
277     msg.setInstanceID(instanceID)
278     msg
279   }
280
281   def newEmptyUserAgreementHistoryMsg() = {
282     val msg = new UserAgreementHistoryMsg
283     msg.setAgreements(new ju.ArrayList[UserAgreementMsg]())
284     msg
285   }
286
287   def newInitialUserAgreementHistoryMsg(
288       initialAgreement: UserAgreementMsg,
289       originalID: String = MessageHelpers.UserAgreementHistoryMsgIDGenerator.nextUID()
290   ) = {
291     val historyMsg = new UserAgreementHistoryMsg
292     historyMsg.setOriginalID(originalID)
293     MessageHelpers.insertUserAgreement(historyMsg, initialAgreement)
294     historyMsg
295   }
296
297   def newUserAgreementFromIMEventMsg(
298       imEvent: IMEventMsg,
299       agreementOriginalID: String = MessageHelpers.UserAgreementMsgIDGenerator.nextUID()
300   ) = {
301
302     val msg = new UserAgreementMsg
303
304     msg.setId(agreementOriginalID)
305     msg.setUserID(imEvent.getUserID)
306     msg.setRelatedIMEventOriginalID(imEvent.getOriginalID)
307     msg.setRole(imEvent.getRole)
308     msg.setValidFromMillis(imEvent.getOccurredMillis)
309     msg.setValidToMillis(java.lang.Long.valueOf(java.lang.Long.MAX_VALUE))
310     msg.setFullPriceTableRef(null) // get from current (= @imEvent.getOccurredMillis) policy
311     msg.setOccurredMillis(TimeHelpers.nowMillis())
312     msg.setRelatedIMEventMsg(imEvent)
313
314     msg
315   }
316
317   def newUserAgreementHistoryMsg(userID: String): UserAgreementHistoryMsg = {
318     val msg = new UserAgreementHistoryMsg
319     msg.setOriginalID(MessageHelpers.UserAgreementHistoryMsgIDGenerator.nextUID())
320     msg.setUserID(userID)
321     msg
322   }
323
324   def newWalletEntriesMsg(entries: ju.List[WalletEntryMsg] = new ju.ArrayList[WalletEntryMsg]()) = {
325     val msg = new WalletEntriesMsg
326     msg.setEntries(entries)
327     msg
328   }
329
330   def newDummyPolicyMsgAt(millis: Long) : PolicyMsg = {
331     PolicyMsg.newBuilder().
332       setOriginalID("").
333       setInStoreID(null).
334       setParentID(null).
335       setValidFromMillis(millis).
336       setValidToMillis(Long.MaxValue).
337       setChargingBehaviors(new ju.ArrayList[String]()).
338       setResourceTypes(new ju.ArrayList[ResourceTypeMsg]()).
339       setRoleMapping(new ju.HashMap[String, FullPriceTableMsg]()).
340       build()
341   }
342
343   def newInitialUserStateMsg(
344       usb: UserStateBootstrap,
345       defaultResourceTypesMap: Map[String, ResourceType],
346       occurredMillis: Long
347   ): UserStateMsg = {
348
349     val bmi = BillingMonthInfo.fromMillis(occurredMillis)
350     val msg = new UserStateMsg
351
352     msg.setUserID(usb.userID)
353     msg.setOccurredMillis(java.lang.Long.valueOf(occurredMillis))
354     msg.setBillingYear(java.lang.Integer.valueOf(bmi.year))
355     msg.setBillingMonth(java.lang.Integer.valueOf(bmi.month))
356     msg.setBillingMonthDay(java.lang.Integer.valueOf(bmi.day))
357     msg.setTotalCredits(java.lang.Double.valueOf(CreditsModel.toTypeInMessage(usb.initialCredits)))
358     msg.setAgreementHistory(newInitialUserAgreementHistoryMsg(usb.initialAgreement.msg))
359     msg.setLatestUpdateMillis(java.lang.Long.valueOf(occurredMillis))
360     msg.setInStoreID(null)
361     msg.setOriginalID(MessageHelpers.UserStateMsgIDGenerator.nextUID())
362     msg.setResourceTypesMap(newResourceTypeMsgsMap(defaultResourceTypesMap))
363     msg.setStateOfResources(new java.util.HashMap())
364     msg.setWalletEntries(new java.util.ArrayList[WalletEntryMsg]())
365     msg
366   }
367 }