2 * Copyright 2011-2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
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.
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.
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.
36 package gr.grnet.aquarium.computation.reason
38 import gr.grnet.aquarium.computation.BillingMonthInfo
39 import gr.grnet.aquarium.event.model.im.IMEventModel
40 import gr.grnet.aquarium.util.shortClassNameOf
43 * Provides information explaining the reason Aquarium calculated a new
44 * [[gr.grnet.aquarium.computation.state.UserState]].
46 case class UserStateChangeReason(
47 details: Map[String, String],
48 billingMonthInfo: Option[BillingMonthInfo],
49 parentReason: Option[UserStateChangeReason]
53 details.contains(UserStateChangeReason.Names.name),
54 "No name present in the details of %s".format(shortClassNameOf(this))
57 private[this] def booleanFromDetails(name: String, default: Boolean) = {
58 details.get(name) match {
68 * Return `true` if the result of the calculation should be stored back to the
69 * [[gr.grnet.aquarium.store.UserStateStore]].
72 // def shouldStoreUserState: Boolean =
73 // booleanFromDetails(UserStateChangeReason.Names.shouldStoreUserState, false)
75 def shouldStoreCalculatedWalletEntries: Boolean =
76 booleanFromDetails(UserStateChangeReason.Names.shouldStoreCalculatedWalletEntries, false)
78 def calculateCreditsForImplicitlyTerminated: Boolean =
79 booleanFromDetails(UserStateChangeReason.Names.calculateCreditsForImplicitlyTerminated, false)
81 def forBillingMonthInfo(bmi: BillingMonthInfo) = {
83 parentReason = Some(this),
84 billingMonthInfo = Some(bmi)
89 // This must be always present
90 details.get(UserStateChangeReason.Names.name).getOrElse("<unknown>")
94 object UserStateChangeReason {
96 final val name = "name"
98 final val imEvent = "imEvent"
99 final val forWhenMillis = "forWhenMillis"
101 final val shouldStoreUserState = "shouldStoreUserState"
102 final val shouldStoreCalculatedWalletEntries = "shouldStoreCalculatedWalletEntries"
103 final val calculateCreditsForImplicitlyTerminated = "calculateCreditsForImplicitlyTerminated"
107 sealed trait UserStateChangeReason_ {
108 def originalReason: UserStateChangeReason_
110 * Return `true` if the result of the calculation should be stored back to the
111 * [[gr.grnet.aquarium.store.UserStateStore]].
114 def shouldStoreUserState: Boolean
116 def shouldStoreCalculatedWalletEntries: Boolean
118 def forPreviousBillingMonth: UserStateChangeReason_
120 def calculateCreditsForImplicitlyTerminated: Boolean
122 def code: UserStateChangeReasonCodes.ChangeReasonCode
126 * Used when the very first user state is saved.
128 object InitialUserStateSetup {
129 def name = "InitialUserStateSetup"
132 * When the user state is initially set up.
134 def apply(parentReason: Option[UserStateChangeReason]) = {
135 UserStateChangeReason(
137 UserStateChangeReason.Names.name -> name//,
138 // UserStateChangeReason.Names.shouldStoreUserState -> true
146 object InitialUserActorSetup {
147 def name = "InitialUserActorSetup"
150 * When the user processing unit (actor) is initially set up.
153 UserStateChangeReason(
155 UserStateChangeReason.Names.name -> name//,
156 // UserStateChangeReason.Names.shouldStoreUserState -> true
164 object NoSpecificChangeReason {
165 def name = "NoSpecificChangeReason"
168 * A calculation made for no specific reason. Can be for testing, for example.
171 UserStateChangeReason(
173 UserStateChangeReason.Names.name -> name
181 object MonthlyBillingCalculation {
182 def name = "MonthlyBillingCalculation"
185 * An authoritative calculation for the billing period.
187 def apply(parentReason: UserStateChangeReason, billingMongthInfo: BillingMonthInfo) = {
188 UserStateChangeReason(
190 UserStateChangeReason.Names.name -> name,
191 // UserStateChangeReason.Names.shouldStoreUserState -> true,
192 UserStateChangeReason.Names.shouldStoreCalculatedWalletEntries -> true.toString,
193 UserStateChangeReason.Names.calculateCreditsForImplicitlyTerminated -> true.toString
195 Some(billingMongthInfo),
201 object RealtimeBillingCalculation {
202 def name = "RealtimeBillingCalculation"
205 * Used for the real-time billing calculation.
207 def apply(parentReason: Option[UserStateChangeReason], forWhenMillis: Long) = {
208 UserStateChangeReason(
210 UserStateChangeReason.Names.name -> name,
211 UserStateChangeReason.Names.forWhenMillis -> forWhenMillis.toString
219 object IMEventArrival {
220 def name = "IMEventArrival"
222 def apply(imEvent: IMEventModel) = {
223 UserStateChangeReason(
225 UserStateChangeReason.Names.name -> name,
226 UserStateChangeReason.Names.imEvent -> imEvent.toJsonString//,
227 // UserStateChangeReason.Names.shouldStoreUserState -> true