3 # Copyright 2016 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
19 @author Varun Prasad (varun.prasad@riftio.com)
27 class IncompatibleAggregationType(Exception):
30 class InvalidAggregationType(Exception):
33 class InvalidAggregationOperation(Exception):
36 class InvalidAggregationValues(Exception):
40 def make_aggregator(field_types
):
41 """A factory method to create the aggregator based on the field type
42 [value_interger, value_string or value_decimal]
45 field_types (list): list of field types to aggregate
46 values (list): List of values
47 aggregation_type (str): Type of aggregation.
50 subclass of ValueAggregator
53 InvalidAggregationType: If Unknown aggregation type is provided
54 InvalidAggregationValues: Raised if a mix of field types are provided.
56 if len(set(field_types
)) != 1:
57 raise InvalidAggregationValues(
58 "Multiple value types provided for aggrgation {}".format(field_types
))
60 field_type
= field_types
[0]
62 if field_type
== IntValueAggregator
.field_name():
63 return IntValueAggregator()
64 elif field_type
== DecimalValueAggregator
.field_name():
65 return DecimalValueAggregator()
66 elif field_type
== StringValueAggregator
.field_name():
67 return StringValueAggregator()
69 raise InvalidAggregationType("Invalid aggregation type")
72 class ValueAggregator():
73 """Base class that defines all the basic operations.
76 aggregation_type (str): Aggregation type to be used to select the
78 values (list): List of values to aggregate.
85 def average(self
, values
):
86 raise InvalidAggregationOperation(
87 "Invalid operation AVERAGE for {}".format(self
.values
))
89 def sum(self
, values
):
90 raise InvalidAggregationOperation(
91 "Invalid operation SUM for {}".format(self
.values
))
93 def maximum(self
, values
):
94 raise InvalidAggregationOperation(
95 "Invalid operation MAXIMUM for {}".format(self
.values
))
97 def minimum(self
, values
):
98 raise InvalidAggregationOperation(
99 "Invalid operation MINIMUM for {}".format(self
.values
))
101 def count(self
, values
):
102 raise InvalidAggregationOperation(
103 "Invalid operation COUNT for {}".format(self
.values
))
105 def aggregate(self
, aggregation_type
, values
):
107 "AVERAGE": self
.average
,
109 "MAXIMUM": self
.maximum
,
110 "MINIMUM": self
.minimum
,
114 op_func
= OP_MAP
.get(aggregation_type
, None)
117 raise InvalidAggregationType("Unknown Aggregation type provided.")
119 return self
.field_name(), op_func(values
)
122 class StringValueAggregator(ValueAggregator
):
125 def field_name(self
):
126 return "value_string"
129 class DecimalValueAggregator(ValueAggregator
):
132 def field_name(self
):
133 return "value_decimal"
135 def average(self
, values
):
136 avg
= functools
.reduce(lambda x
, y
: x
+ y
, values
) / len(values
)
139 def sum(self
, values
):
140 return functools
.reduce(lambda x
, y
: x
+ y
, values
)
142 def maximum(self
, values
):
145 def minimum(self
, values
):
148 def count(self
, values
):
152 class IntValueAggregator(DecimalValueAggregator
):
155 def field_name(self
):
156 return "value_integer"
158 def average(self
, values
):
159 avg
= functools
.reduce(lambda x
, y
: x
+ y
, values
) / len(values
)