package gr.grnet.aquarium.logic.credits.dsl
-import gr.grnet.aquarium.util.yaml.YAMLHelpers
import gr.grnet.aquarium.util.Loggable
-import gr.grnet.aquarium.logic.credits.model.{CreditStructureClass, CreditStructure}
-import java.io.{StringReader, InputStreamReader, Reader, InputStream}
/**
*
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
object CreditsDSL extends Loggable {
- object Keys {
- val StructureClass = "structure_class"
- val Id = "id"
- val Name = "name"
- val Units = "units"
- val Grouping = "grouping"
- }
- def parseString(s: CharSequence): CreditStructureClass = {
- doParse(new StringReader(s.toString))
- }
-
- def parseStream(in: InputStream, encoding: String = "UTF-8", closeIn: Boolean = true): CreditStructureClass = {
- doParse(new InputStreamReader(in, encoding), closeIn)
- }
-
- // FIXME: implement
- private def doParse(r: Reader, closeReader: Boolean = true): CreditStructureClass = {
- val creditsDocument = YAMLHelpers.loadYAML(r, closeReader)
-
- val ystructureDef = creditsDocument / Keys.StructureClass
- val yId = ystructureDef / Keys.Id
- val yname = ystructureDef / Keys.Name
- val yunits = ystructureDef / Keys.Units
- val ygrouping = ystructureDef / Keys.Grouping
-
- logger.debug("name = %s".format(yname))
- logger.debug("units = %s".format(yunits))
- logger.debug("grouping = %s".format(ygrouping))
-
- CreditStructureClass("", "", Nil)
- }
}
\ No newline at end of file
*
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
-case class CreditAmount(amount: Long, creditOrigin: CreditOrigin)
\ No newline at end of file
+case class CreditAmount(amount: Long, origin: CreditOrigin)
\ No newline at end of file
--- /dev/null
+package gr.grnet.aquarium.logic.credits.model
+
+/**
+ *
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+sealed trait CreditDistributionHow {
+ def name: String
+ def attributes: Map[String, String]
+}
+
+object CreditDistributionHow {
+ object Names {
+ val CreditDistributionHowFixedAny = "CreditDistributionHowFixedAny"
+ val CreditDistributionHowFixedEqual = "CreditDistributionHowFixedEqual"
+ val CreditDistributionHowOnDemandUnlimited = "CreditDistributionHowOnDemandUnlimited"
+ val CreditDistributionHowOnDemandMax = "CreditDistributionHowOnDemandMax"
+ val CreditDistributionHowAlgorithmic = "CreditDistributionHowAlgorithmic"
+
+ }
+}
+
+case object CreditDistributionHowFixedAny extends CreditDistributionHow {
+ def name = CreditDistributionHow.Names.CreditDistributionHowFixedAny
+ def attributes = Map()
+}
+
+case object CreditDistributionHowFixedEqual extends CreditDistributionHow {
+ def name = CreditDistributionHow.Names.CreditDistributionHowFixedEqual
+ def attributes = Map()
+}
+
+case object CreditDistributionHowOnDemandUnlimited extends CreditDistributionHow {
+ def name = CreditDistributionHow.Names.CreditDistributionHowOnDemandUnlimited
+ def attributes = Map()
+}
+
+case class CreditDistributionHowOnDemandMax(max: Long) extends CreditDistributionHow {
+ def name = CreditDistributionHow.Names.CreditDistributionHowOnDemandMax
+ def attributes = Map("max" -> max.toString)
+}
+
+case class CreditDistributionHowAlgorithmic(algorithm: String) extends CreditDistributionHow {
+ def name = CreditDistributionHow.Names.CreditDistributionHowAlgorithmic
+ def attributes = Map("algorithm" -> algorithm)
+}
\ No newline at end of file
--- /dev/null
+package gr.grnet.aquarium.logic.credits.model
+
+/**
+ *
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+case class CreditDistributionPolicy(when: CreditDistributionWhen, how: CreditDistributionHow)
\ No newline at end of file
+++ /dev/null
-package gr.grnet.aquarium.logic.credits.model
-
-/**
- * The credit distribution type representation.
- *
- * This dictates how credits are distributed at lower level structure parts, for example
- * how a University distributes credits to its Departments.
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-sealed trait CreditDistributionType {
- def name: String
- def value: Int
-
- def isUnknown = false
- def isFixed = isFixedAny || isFixedEqual
- def isFixedAny = false
- def isFixedEqual = false
- def isOnDemandUnlimited = false
- def isOnDemandMax = false
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-sealed abstract class CreditDistributionTypeSkeleton(_name: String, _value: Int) extends CreditDistributionType {
- def name = _name
- def value = _value
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case object FixedAnyCreditDistributionType
- extends CreditDistributionTypeSkeleton(CreditDistributionType.Names.FixedAny, CreditDistributionType.Values.FixedEqual) {
-
- override def isFixedAny = true
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case object FixedEqualCreditDistributionType
- extends CreditDistributionTypeSkeleton(CreditDistributionType.Names.FixedAny, CreditDistributionType.Values.FixedEqual) {
-
- override def isFixedEqual = true
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case object OnDemandUnlimitedCreditDistributionType
- extends CreditDistributionTypeSkeleton(CreditDistributionType.Names.OnDemandUnlimited, CreditDistributionType.Values.OnDemandUnlimited) {
-
- override def isOnDemandUnlimited = true
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case object OnDemandMaxCreditDistributionType
- extends CreditDistributionTypeSkeleton(CreditDistributionType.Names.OnDemandMax, CreditDistributionType.Values.OnDemandMax) {
-
- override def isOnDemandMax = true
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case class UnknownCreditDistributionType(reason: Option[String]) extends CreditDistributionTypeSkeleton(CreditDistributionType.Names.Unknown, CreditDistributionType.Values.Unknown) {
- override def isUnknown = true
-}
-
-object CreditDistributionType {
- object Values {
- /**
- * Credits are distributed (pushed) in fixed values and parts can be divided at will.
- */
- val FixedAny = 10
-
- /**
- * Credits are distributed (pushed) in fixed values and parts are divided equally.
- */
- val FixedEqual = 20
-
- /**
- * Credits are distributed (pulled) on demand.
- */
- val OnDemandUnlimited = 30
-
- /**
- * Credits are distributed (pulled) on demand but up to a maximum value.
- */
- val OnDemandMax = 40
-
- /**
- * Error indicator
- */
- val Unknown = -1
- }
-
- object Names {
- val FixedAny = "FixedAny"
- val FixedEqual = "FixedEqual"
- val OnDemandUnlimited = "OnDemandUnlimited"
- val OnDemandMax = "OnDemandMax"
- val Unknown = "Unknown"
-
- val FixedAny_Lower = FixedAny.toLowerCase
- val FixedEqual_Lower = FixedEqual.toLowerCase
- val OnDemandUnlimited_Lower = OnDemandUnlimited.toLowerCase
- val OnDemandMax_Lower = OnDemandMax.toLowerCase
- val Unknown_Lower = Unknown.toLowerCase
- }
-
- def fromValue(value: Int): CreditDistributionType = {
- value match {
- case Values.FixedAny => FixedAnyCreditDistributionType
- case Values.FixedEqual => FixedEqualCreditDistributionType
- case Values.OnDemandUnlimited => OnDemandUnlimitedCreditDistributionType
- case Values.OnDemandMax => OnDemandMaxCreditDistributionType
- case Values.Unknown => UnknownCreditDistributionType(None)
- case value => UnknownCreditDistributionType(Some("Bad value %s".format(value)))
- }
- }
-
- def fromName(name: String): CreditDistributionType = {
- name match {
- case Names.FixedAny => FixedAnyCreditDistributionType
- case Names.FixedEqual => FixedEqualCreditDistributionType
- case Names.OnDemandUnlimited => OnDemandUnlimitedCreditDistributionType
- case Names.OnDemandMax => OnDemandMaxCreditDistributionType
- case Names.Unknown => UnknownCreditDistributionType(None)
- case value => UnknownCreditDistributionType(Some("Bad value %s".format(value)))
- }
- }
-
- def fromNameIgnoreCase(name: String): CreditDistributionType = {
- name match {
- case null => UnknownCreditDistributionType(Some("null name"))
- case _ => name.toLowerCase match {
- case Names.FixedAny_Lower => FixedAnyCreditDistributionType
- case Names.FixedEqual_Lower => FixedEqualCreditDistributionType
- case Names.OnDemandUnlimited_Lower => OnDemandUnlimitedCreditDistributionType
- case Names.OnDemandMax_Lower => OnDemandMaxCreditDistributionType
- case Names.Unknown_Lower => UnknownCreditDistributionType(None)
- case value => UnknownCreditDistributionType(Some("Bad value %s".format(value)))
- }
- }
- }
-}
--- /dev/null
+package gr.grnet.aquarium.logic.credits.model
+
+/**
+ *
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+sealed trait CreditDistributionWhen {
+ def name: String
+ def attributes: Map[String, String]
+}
+
+object CreditDistributionWhen {
+ object Names {
+ val CreditDistributionWhenManual = "CreditDistributionWhenManual"
+ val CreditDistributionWhenPeriodic = "CreditDistributionWhenPeriodic"
+ val CreditDistributionWhenOnCreditArrival = "CreditDistributionWhenOnCreditArrival"
+ }
+}
+
+case object CreditDistributionWhenManual extends CreditDistributionWhen {
+ def name = CreditDistributionWhen.Names.CreditDistributionWhenManual
+ def attributes = Map()
+}
+
+case class CreditDistributionWhenPeriodic(cronPeriod: String) extends CreditDistributionWhen {
+ def name = CreditDistributionWhen.Names.CreditDistributionWhenPeriodic
+ def attributes = Map("cronPeriod" -> cronPeriod)
+}
+
+case object CreditDistributionWhenOnCreditArrival extends CreditDistributionWhen {
+ def name = CreditDistributionWhen.Names.CreditDistributionWhenOnCreditArrival
+ def attributes = Map()
+}
\ No newline at end of file
package gr.grnet.aquarium.logic.credits.model
+import java.net.URI
+
+
/**
* A credit holder is the entity to which credits can be assigned.
*
+ * This can be the wallet.
+ *
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
-case class CreditHolder(name: String, creditHolderClass: CreditHolderClass) {
- def isSingleHolderClass = creditHolderClass.isSingleHolderClass
- def isCompositeHolderClass = creditHolderClass.isCompositeHolderClass
-}
\ No newline at end of file
+sealed trait CreditHolder {
+ def name: String
+ def label: String
+ def isSingle: Boolean
+ def isGroup: Boolean
+ def members: List[String]
+ def wallet: List[CreditAmount]
+}
+
+case class UserCreditHolder(name: String, label: String, wallet: List[CreditAmount]) extends CreditHolder {
+ def isSingle = true
+ def isGroup = false
+ def members = Nil
+}
+
+case class GroupCreditHolder(name: String, label: String, members: List[String], wallet: List[CreditAmount]) extends CreditHolder {
+ def isSingle = false
+ def isGroup = true
+}
+
+++ /dev/null
-package gr.grnet.aquarium.logic.credits.model
-
-/**
- * A credit holder definition that is used to instantiate credit holders.
- *
- * Notice the OOP parlance resemblance.
-
- * Credit holders can be composite or not.
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-sealed trait CreditHolderClass {
- def name: String
- def isSingleHolderClass: Boolean
- def isCompositeHolderClass: Boolean
- def members: List[CreditHolderClass]
- def creditDistributions: MembersCreditDistributionMap
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case class SingleCreditHolderClass(name: String) extends CreditHolderClass {
- def members = Nil
- def creditDistributions = Map()
- def isSingleHolderClass = true
- def isCompositeHolderClass = false
-}
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case class CompositeCreditHolderClass(
- name: String,
- members: List[CreditHolderClass],
- creditDistributions: MembersCreditDistributionMap)
- extends CreditHolderClass {
-
- def isSingleHolderClass = true
- def isCompositeHolderClass = true
-}
\ No newline at end of file
def name = CreditOrigin.Names.Own
}
-case class InheritedCreditOrigin(creditHolder: CreditHolderClass, creditDistributionType: CreditDistributionType) extends CreditOrigin {
+case class InheritedCreditOrigin(creditHolder: CreditHolder, creditDistributionPolicy: CreditDistributionPolicy) extends CreditOrigin {
override def isInherited = true
def name = CreditOrigin.Names.Own
+++ /dev/null
-package gr.grnet.aquarium.logic.credits.model
-
-/**
- * The actual credit structure instance for a particular client
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case class CreditStructure(
- id: String,
- name: String,
- creditStructureDef: CreditStructureClass,
- members: List[CreditHolder])
\ No newline at end of file
+++ /dev/null
-package gr.grnet.aquarium.logic.credits.model
-
-/**
- * The definition of a credit structure.
- * This could mimic the organizational structure of the client though something like that is not necessary.
- *
- * These are top-level and system-wide definitions that can be reused.
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>.
- */
-case class CreditStructureClass(
- id: String,
- name: String,
- memberClasses: List[CreditHolderClass])
* For a member of a structure, provide the credit distribution type
* the parent follows for this member.
*/
- type MembersCreditDistributionMap = Map[CreditHolderClass, List[CreditDistributionType]]
+ type MembersCreditDistributionMap = Map[CreditHolder, List[CreditDistributionPolicy]]
}
\ No newline at end of file
*
* @author Georgios Gousios <gousiosg@gmail.com>.
*/
-case class YAMLDoubleNode(double: Double) extends YAMLNode {
+case class YAMLDoubleNode(path: String, double: Double) extends YAMLNode {
def /(childName: String) = YAMLEmptyNode
override def doubleValue = double
override def isDouble = true
+
+ def withPath(newPath: String) = this.copy(path = newPath)
}
def /(childName: String) = YAMLEmptyNode
override def isEmpty = true
+
+ def path = ""
+ def withPath(newPath: String) = this
}
*
* @author Georgios Gousios <gousiosg@gmail.com>.
*/
-case class YAMLIntNode(int: Int) extends YAMLNode {
+case class YAMLIntNode(path: String, int: Int) extends YAMLNode {
def /(childName: String) = YAMLEmptyNode
override def intValue = int
-
override def isInt = true
+
+
+ def withPath(newPath: String) = this.copy(path = newPath)
}
*
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
-case class YAMLListNode(list: List[YAMLNode]) extends YAMLNode {
+case class YAMLListNode(path: String, list: List[YAMLNode]) extends YAMLNode {
def /(childName: String) = YAMLEmptyNode
override def listValue = list
case Nil => YAMLEmptyNode
case h :: _ => h
}
- def tail = YAMLListNode(list.tail)
+ def tail = YAMLListNode(path + "::tail", list.tail)
override def isEmpty = list.isEmpty
+
+ override def foreach[T](f: (YAMLNode) => T) = {
+ for(node <- listValue) {
+ f(node)
+ }
+ }
+
+ def withPath(newPath: String) = this.copy(path = newPath)
}
\ No newline at end of file
*
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
-case class YAMLMapNode(map: mutable.Map[String, YAMLNode]) extends YAMLNode {
+case class YAMLMapNode(path: String, map: mutable.Map[String, YAMLNode]) extends YAMLNode {
def /(childName: String) = map.get(childName) match {
- case Some(child) => child
+ case Some(child) => child.withPath(YAMLNode.concatPaths(path, childName))
case None => YAMLEmptyNode
}
override def mapValue = map.toMap // get an immutable version
override def isMap = true
+
+ def withPath(newPath: String) = this.copy(path = newPath)
}
trait YAMLNode {
def /(childName: String): YAMLNode
+ def name = path.substring(path.lastIndexOf('/') + 1)
+
+ def path: String
+ def withPath(newPath: String): YAMLNode
+
def intValue: Int = 0
def doubleValue: Double = 0.0
def stringValue: String = null
def isMap = false
def isList = false
def isUnknown = false
+
+ def foreach[T](f: YAMLNode => T): Unit = {}
}
/**
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
object YAMLNode {
- def apply(obj: AnyRef): YAMLNode = {
+ def concatPaths(parent: String, child: String) = {
+ if(parent == "/") {
+ if(child startsWith "/") {
+ child
+ } else {
+ "/" + child
+ }
+ } else {
+ parent + "/" + child
+ }
+ }
+
+ def indexedPath(basePath: String, index: Int) = "%s[%s]".format(basePath, index)
+
+ def apply(obj: AnyRef, basePath: String = "/"): YAMLNode = {
obj match {
case null =>
YAMLEmptyNode
- case map: JMap[_, _] =>
- val workingMap: mutable.Map[String, AnyRef] = map.asInstanceOf[JMap[String, AnyRef]]
- val mappedMap = workingMap map {
+ case javaMap: JMap[_, _] =>
+ val scalaMap: mutable.Map[String, AnyRef] = javaMap.asInstanceOf[JMap[String, AnyRef]]
+ val nodeMap = scalaMap map {
case (key, value) if value.isInstanceOf[YAMLNode] =>
- (key, value).asInstanceOf[(String, YAMLNode)]
+ val yvalue = value.asInstanceOf[YAMLNode]//.withPath(concatPaths(basePath, key))
+ (key, yvalue)
case (key, value) =>
- (key, apply(value))
+ (key, apply(value, concatPaths(basePath, key)))
}
- YAMLMapNode(mappedMap)
-// case map: mutable.Map[_, _] =>
-// val workingMap = map
-// val mappedMap = workingMap map {
-// case (key, value) if value.isInstanceOf[YAMLNode] =>
-// (key, value)
-// case (key, value) =>
-// (key, newYAMLNode(value))
-// }
-// YAMLMapNode(mappedMap)
- case list: JList[_] =>
- val workingList: mutable.Buffer[AnyRef] = list.asInstanceOf[JList[AnyRef]]
- val mappedList = workingList.map(apply(_)).toList
- YAMLListNode(mappedList)
+ YAMLMapNode(basePath, nodeMap)
+ case javaList: JList[_] =>
+ val scalaList: mutable.Buffer[AnyRef] = javaList.asInstanceOf[JList[AnyRef]]
+ val nodeList = scalaList.zipWithIndex.map { case (elem, index) => apply(elem, indexedPath(basePath, index)) }.toList
+ YAMLListNode(basePath, nodeList)
case string: String =>
- YAMLStringNode(string)
+ YAMLStringNode(basePath, string)
case x: YAMLNode => x
case int: java.lang.Integer =>
- YAMLIntNode(int)
+ YAMLIntNode(basePath, int)
case double: java.lang.Double =>
YAMLDoubleNode(double)
case obj =>
*
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
-case class YAMLStringNode(string: String) extends YAMLNode {
+case class YAMLStringNode(path: String, string: String) extends YAMLNode {
def /(childName: String) = YAMLEmptyNode
override def stringValue = string
override def isString = true
+
+ def withPath(newPath: String) = this.copy(path = newPath)
}
def /(childName: String) = this
override def isUnknown = false
+
+ def path = ""
+ def withPath(newPath: String) = this
}
--- /dev/null
+credit-distribution-policies:
+ - how:
+ - types:
+ - FixedAny
+ - FixedEqual
+ - OnDemandUnlimited
+ - OnDemandMax
+ - Algorithmic
+ - aliases: # aliases define named sets of credit distribution types
+ - AliasAny:
+ - FixedAny
+ - FixedEqual
+ - OnDemandUnlimited
+ - OnDemandMax
+ - AliasFixed:
+ - FixedAny
+ - FixedEqual
+ - AliasOnDemand:
+ - OnDemandUnlimited
+ - OnDemandMax
+ - when:
+ - OnCreditArrival
+ - Manual
+ - Periodic
\ No newline at end of file
+++ /dev/null
-credit-distribution:
- - types:
- - FixedAny
- - FixedEqual
- - OnDemandUnlimited
- - OnDemandMax
- - Unknown
- - aliases: # aliases define named sets of credit distribution types
- - AliasAny:
- - FixedAny
- - FixedEqual
- - OnDemandUnlimited
- - OnDemandMax
- - AliasFixed:
- - FixedAny
- - FixedEqual
- - OnDemandUnlimited
- - OnDemandMax
- - AliasOnDemand:
- - OnDemandUnlimited
- - OnDemandMax
\ No newline at end of file
--- /dev/null
+credit_group:
+ name: Lab
+ label: lab
+ owner: some:uri # another group or user
+ members:
+ - memberURI_1 # Can be teaching assistant
+ - memberURI_2 # Can be a student
+ - memberURI_3
+ credit_distribution:
+ - when: OnCreditArrival
+ - how: FixedEqual
+++ /dev/null
-credit-holder-protos:
- - Single:
- id: "gr.grnet.aquarium.credits.model.holder.Single"
- - Composite:
- id: "gr.grnet.aquarium.credits.model.holder.Composite"
\ No newline at end of file
+++ /dev/null
-# Definition of a client type (read: Company, Organization, …)
-
-# This is not necessarily the organizational structure of the client.
-# It may reflect the organizational structure but it actually is the credit structure of the particular client.
-# The credit structure defines the ways that credits can be distributed among the participants.
-#
-# The idea is to provide the policy here and map it to our low-end, generic credit transfer/grouping
-# mechanism(s).
-
-# Also, these structures are kind of static and are considered integral part of the business case each client
-# represents/is characterized by.
-
-structure_class:
- id: "gr.grnet.aquarium.credit.struct.GreekUniversityCreditStructure"
- name: Greek University Structure
- credit_holders:
- - University:
- name: University # if omitted, taken as the credit_holders key (University in this case)
- id: University # if omitted, taken as the name (University in this case)
- type: Composite # if omitted, inferred by the presence of members
- members:
- - Department: # Use the id here and not the name
- credit_distribution: # List of credit distribution types
- - AliasFixed # only specific amounts are given from Universities to Departments
- - Lab:
- credit_distribution:
- - AliasFixed # only specific amounts are given from Universities to Labs
- - Department:
- members:
- - Professor:
- credit_distribution:
- - AliasAny # A Department has the ability to distribute credits to its Professors in the most flexible way
- - Lab:
- credit_distribution:
- - AliasAny # A Department has the ability to distribute credits to its Labs in the most flexible way
- - Course:
- credit_distribution:
- - AliasAny # A Department has the ability to distribute credits to its Courses in the most flexible way
- - Student: # Is this a undergrad, a postgrad, a PhD?
- credit_distribution:
- - AliasFixed # only fixed amounts of credits are distributed to Students
-
- - Lab:
- members:
- - Course:
- credit_distribution:
- - AliasFixed # Lab members get only fixed amounts
- - Course:
- members:
- - Professor # If no credit distribution is defined, then AliasAny is assumed
- - Exercise
- - Student
- - Professor
- - Student
- - Exercise
-
- distribution: # describes the policy for the distribution of credits
-
import org.junit.Test
import org.junit.Assert._
-import gr.grnet.aquarium.logic.credits.dsl.CreditsDSL
-import gr.grnet.aquarium.logic.credits.model.CreditStructureClass
import java.io.{Reader, InputStreamReader, InputStream, StringReader}
-import gr.grnet.aquarium.util.yaml.YAMLHelpers
-import gr.grnet.aquarium.logic.credits.model.CreditStructureClass._
import gr.grnet.aquarium.util.Loggable
+import gr.grnet.aquarium.util.yaml.{YAMLNode, YAMLHelpers}
+import gr.grnet.aquarium.logic.credits.model.GroupCreditHolder
class CreditDSLTest extends Loggable {
object Keys {
- val StructureClass = "structure_class"
- val Id = "id"
- val Name = "name"
- val Units = "units"
- val Grouping = "grouping"
+ val credit_group = "credit_group"
+ val name = "name"
+ val label = "label"
+ val owner = "owner"
+ val members = "members"
+ val credit_distribution = "credit_distribution"
}
- def parseString(s: CharSequence): CreditStructureClass = {
+ def parseResource(name: String): GroupCreditHolder = {
+ parseStream(getClass.getClassLoader.getResourceAsStream(name))
+ }
+
+ def parseString(s: CharSequence): GroupCreditHolder = {
doParse(new StringReader(s.toString))
}
- def parseStream(in: InputStream, encoding: String = "UTF-8", closeIn: Boolean = true): CreditStructureClass = {
+ def parseStream(in: InputStream, encoding: String = "UTF-8", closeIn: Boolean = true): GroupCreditHolder = {
doParse(new InputStreamReader(in, encoding), closeIn)
}
- // FIXME: implement
- private def doParse(r: Reader, closeReader: Boolean = true): CreditStructureClass = {
- val creditsDocument = YAMLHelpers.loadYAML(r, closeReader)
+ def parseChild[T](node: YAMLNode, name: String): YAMLNode = {
+ val y = node / name
+ val yname = y.name
+ assert(name == yname, "Parsed name [%s] equals requested name [%s]".format(yname, name))
+ logger.debug("Parsed [%s] %s".format(yname, y))
+ y
+ }
- val ystructureDef = creditsDocument / Keys.StructureClass
- val yId = ystructureDef / Keys.Id
- val yname = ystructureDef / Keys.Name
- val yunits = ystructureDef / Keys.Units
- val ygrouping = ystructureDef / Keys.Grouping
+ // FIXME: implement
+ private def doParse(r: Reader, closeReader: Boolean = true): GroupCreditHolder = {
+ val document = YAMLHelpers.loadYAML(r, closeReader)
- logger.debug("name = %s".format(yname))
- logger.debug("units = %s".format(yunits))
- logger.debug("grouping = %s".format(ygrouping))
+ val ygroup = parseChild(document, Keys.credit_group)
+ val yname = parseChild(ygroup, Keys.name)
+ val yabel = parseChild(ygroup, Keys.label)
+ val yowner = parseChild(ygroup, Keys.owner)
+ val ymembers = parseChild(ygroup, Keys.members)
+ val ydistrib = parseChild(ygroup, Keys.credit_distribution)
- CreditStructureClass("", "", Nil)
+ GroupCreditHolder("", "", Nil, Nil)
}
@Test
def testDSLLoad = {
- val structure = CreditsDSL.parseStream(getClass.getClassLoader.getResourceAsStream("credit-structure-greek-uni.yaml"))
+ val structure = parseResource("credit-group-lab.yaml")
assertNotNull(structure)
}
}
\ No newline at end of file