WIP: Remodeling events
[aquarium] / src / main / scala / gr / grnet / aquarium / events / im / IMEvent.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
37 package events
38 package im
39
40 import gr.grnet.aquarium.util.makeString
41 import gr.grnet.aquarium.Configurator._
42 import com.ckkloverdos.maybe.{Failed, NoVal, Just}
43 import converter.{StdConverters, JsonTextFormat}
44
45 /**
46  * Represents an event from the `Identity Management` (IM) external system.
47  *
48  * @author Georgios Gousios <gousiosg@gmail.com>
49  */
50 case class _IMEvent(
51                     override val id: String, // The id at the sender side
52                     override val occurredMillis: Long, // When it occurred at the sender side
53                     override val receivedMillis: Long, // When it was received by Aquarium
54                     override val userID: String,
55                     clientID: String,
56                     isActive: Boolean,
57                     role: String,
58                     override val eventVersion: String,
59                     eventType: String,
60                     override val details: Map[String, String],
61                     _id: String = "")
62   extends AquariumEventSkeleton(id, occurredMillis, receivedMillis, eventVersion) with IMEventModel {
63
64
65   //  assert(eventType.equalsIgnoreCase(IMEvent.EventTypes.create) ||
66   //    eventType.equalsIgnoreCase(IMEvent.EventTypes.modify))
67
68   //  assert(!role.isEmpty)
69
70   /**
71    * Validate this event according to the following rules:
72    *
73    * Valid event states: `(eventType, state)`:
74    * - `a := CREATE, ACTIVE`
75    * - `b := MODIFY, ACTIVE`
76    * - `c := MODIFY, SUSPENDED`
77    *
78    * Valid transitions:
79    * - `(non-existent) -> a`
80    * - `a -> c`
81    * - `c -> b`
82    */
83   def validate: Boolean = {
84
85     MasterConfigurator.userStateStore.findUserStateByUserId(userID) match {
86       case Just(x) =>
87         if(eventType.equalsIgnoreCase(_IMEvent.EventTypes.create)) {
88           logger.warn("User to create exists: IMEvent".format(this.toJson));
89           return false
90         }
91       case NoVal =>
92         if(!eventType.equalsIgnoreCase(_IMEvent.EventTypes.modify)) {
93           logger.warn("Inexistent user to modify. IMEvent:".format(this.toJson))
94           return false
95         }
96       case Failed(x) =>
97         logger.warn("Error retrieving user state: %s".format(x))
98     }
99
100     true
101   }
102
103   def withReceivedMillis(millis: Long) = copy(receivedMillis = millis)
104 }
105
106 object _IMEvent {
107
108   object EventTypes {
109     val create = "create"
110     val modify = "modify"
111   }
112
113   def fromJson(json: String): _IMEvent = {
114     StdConverters.StdConverters.convertEx[_IMEvent](JsonTextFormat(json))
115   }
116
117   def fromBytes(bytes: Array[Byte]): _IMEvent = {
118     StdConverters.StdConverters.convertEx[_IMEvent](JsonTextFormat(makeString(bytes)))
119   }
120
121   object JsonNames {
122     final val _id = "_id"
123     final val id = "id"
124
125     final val occurredMillis = "occurredMillis"
126     final val receivedMillis = "receivedMillis"
127     final val userID = "userID"
128     final val clientID = "clientID"
129     final val isActive = "isActive"
130     final val role = "role"
131     final val eventVersion = "eventVersion"
132     final val eventType = "eventType"
133     final val details = "details"
134   }
135
136 }