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.message.avro
38 import gr.grnet.aquarium.message.avro.gen.{_EffectivePriceTable, _FullPriceTable}
39 import gr.grnet.aquarium.AquariumInternalError
40 import gr.grnet.aquarium.util.shortNameOfType
41 import gr.grnet.aquarium.util.LogHelpers.Debug
42 import org.slf4j.Logger
43 import scala.annotation.tailrec
44 import java.{util ⇒ ju}
48 * @author Christos KK Loverdos <loverdos@gmail.com>
50 object FullPriceTableHelpers {
51 final val DefaultSelectorKey = "default"
53 def effectivePriceTableOfSelectorForResource(
54 fullPriceTable: _FullPriceTable,
55 selectorPath: List[CharSequence],
58 ): _EffectivePriceTable = {
60 // Most of the code is for exceptional cases, which we identify in detail.
63 partialSelectorPath: List[CharSequence],
64 partialSelectorData: Any
65 ): _EffectivePriceTable = {
67 Debug(logger, "find: ")
68 Debug(logger, " partialSelectorPath = %s", partialSelectorPath.mkString("/"))
69 Debug(logger, " partialSelectorData = %s", partialSelectorData)
71 partialSelectorPath match {
72 case selector :: Nil ⇒
73 // One selector, meaning that the selectorData must be a Map[String, EffectivePriceTable]
74 partialSelectorData match {
75 case selectorMap: ju.Map[_,_] ⇒
76 // The selectorData is a map indeed
77 selectorMap.asInstanceOf[ju.Map[String, _]].get(selector) match {
79 // The selectorData is a map but it does nto contain the selector
80 throw new AquariumInternalError(
81 "[AQU-SEL-002] Cannot select path %s for resource %s. Nothing found at partial selector path %s".format(
82 selectorPath.mkString("/"),
84 partialSelectorPath.mkString("/")
88 case selected: _EffectivePriceTable ⇒
89 // Yes, it is a map of the right type (OK, we assume keys are always Strings)
90 // (we only check the value type)
94 // The selectorData is a map but the value is not of the required type
95 throw new AquariumInternalError(
96 "[AQU-SEL-001] Cannot select path %s for resource %s. Found %s instead of an %s at partial selector path %s".format(
97 selectorPath.mkString("/"),
100 shortNameOfType[_EffectivePriceTable],
101 partialSelectorPath.mkString("/")
108 // The selectorData is not a map. So we have just one final selector but no map to select from.
109 throw new AquariumInternalError(
110 "[AQU-SEL-003] Cannot select path %s for resource %s. Found %s instead of a Map at partial selector path %s".format(
111 selectorPath.mkString("/"),
114 partialSelectorPath.mkString("/")
119 case selector :: selectorTail ⇒
120 // More than one selector in the path, meaning that the selectorData must be a Map[String, Map[String, _]]
121 partialSelectorData match {
122 case selectorMap: ju.Map[_,_] ⇒
123 // The selectorData is a map indeed
124 selectorMap.asInstanceOf[ju.Map[String,_]].get(selector) match {
126 // The selectorData is a map but it does not contain the selector
127 throw new AquariumInternalError(
128 "[AQU-SEL-005] Cannot select path %s for resource %s. Nothing found at partial selector path %s".format(
129 selectorPath.mkString("/"),
131 partialSelectorPath.mkString("/")
135 case furtherSelectorMap: ju.Map[_,_] ⇒
136 // The selectorData is a map and we found the respective value for the selector to be a map.
137 find(selectorTail, furtherSelectorMap)
140 // The selectorData is a map but the respective value is not a map, so that
141 // the selectorTail path cannot be used.
142 throw new AquariumInternalError(
143 "[AQU-SEL-004] Cannot select path %s for resource %s. Found %s instead of a Map at partial selector path %s".format(
144 selectorPath.mkString("/"),
147 partialSelectorPath.mkString("/")
153 // The selectorData is not a Map. So we have more than one selectors but no map to select from.
154 throw new AquariumInternalError(
155 "[AQU-SEL-006] Cannot select path %s for resource %s. Found %s instead of a Map at partial selector path %s".format(
156 selectorPath.mkString("/"),
159 partialSelectorPath.mkString("/")
165 throw new AquariumInternalError(
166 "[AQU-SEL-007] No selector path for resource %s".format(resource)
172 Debug(logger, "effectivePriceTableOfSelectorForResource:")
173 Debug(logger, " selectorPath = %s", selectorPath.mkString("/"))
175 val selectorData = fullPriceTable.getPerResource().get(resource)
176 if(selectorData eq null) {
177 throw new AquariumInternalError("Unknown resource type '%s'", resource)
180 Debug(logger, " selectorData = %s", selectorData)
181 find(selectorPath, selectorData)