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.charging.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 ChargingReason(
47 details: Map[String, Any],
48 billingMonthInfo: Option[BillingMonthInfo],
49 parentReason: Option[ChargingReason]
53 details.contains(ChargingReason.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 {
60 value.toString.toBoolean
67 def calculateCreditsForImplicitlyTerminated: Boolean =
68 booleanFromDetails(ChargingReason.Names.calculateCreditsForImplicitlyTerminated, false)
70 def forBillingMonthInfo(bmi: BillingMonthInfo) = {
72 parentReason = Some(this),
73 billingMonthInfo = Some(bmi)
78 // This must be always present
79 details.get(ChargingReason.Names.name).map(_.toString).getOrElse("<unknown>")
83 object ChargingReason {
86 final val name = "name"
88 final val imEvent = "imEvent"
89 final val forWhenMillis = "forWhenMillis"
91 final val calculateCreditsForImplicitlyTerminated = "calculateCreditsForImplicitlyTerminated"
97 * Used when the very first user state is saved.
99 object InitialUserStateSetup {
100 def name = "InitialUserStateSetup"
103 * When the user state is initially set up.
105 def apply(parentReason: Option[ChargingReason]) = {
108 ChargingReason.Names.name -> name
116 object InitialUserActorSetup {
117 def name = "InitialUserActorSetup"
120 * When the user processing unit (actor) is initially set up.
125 ChargingReason.Names.name -> name
133 object NoSpecificChargingReason {
134 def name = "NoSpecificChargingReason"
137 * A calculation made for no specific reason. Can be for testing, for example.
142 ChargingReason.Names.name -> name
150 object MonthlyBillChargingReason {
151 def name = "MonthlyBillChargingReason"
154 * An authoritative calculation for the billing period.
156 def apply(parentReason: ChargingReason, billingMongthInfo: BillingMonthInfo) = {
159 ChargingReason.Names.name -> name,
160 ChargingReason.Names.calculateCreditsForImplicitlyTerminated -> true.toString
162 Some(billingMongthInfo),
168 object RealtimeChargingReason {
169 def name = "RealtimeChargingReason"
172 * Used for the real-time billing calculation.
174 def apply(parentReason: Option[ChargingReason], forWhenMillis: Long) = {
177 ChargingReason.Names.name -> name,
178 ChargingReason.Names.forWhenMillis -> forWhenMillis.toString
186 object IMEventArrival {
187 def name = "IMEventArrival"
189 def apply(imEvent: IMEventModel) = {
192 ChargingReason.Names.name -> name,
193 ChargingReason.Names.imEvent -> imEvent.toJsonString