/razpub/src/razie/Assets.scala

http://razpub.googlecode.com/ · Scala · 239 lines · 102 code · 39 blank · 98 comment · 34 complexity · 404467897e344590ca5fb8e215c32491 MD5 · raw file

  1. /**
  2. * Razvan's public code. Copyright 2008 based on Apache license (share alike) see LICENSE.txt for
  3. * details. No warranty implied nor any liability assumed for this code.
  4. */
  5. package razie
  6. import org.w3c.dom._
  7. import com.razie.pub.agent._
  8. import com.razie.pub.lightsoa._
  9. import com.razie.pub.assets._
  10. //import com.razie.assets._
  11. import scala.collection.mutable._
  12. import razie._
  13. import razie.base._
  14. import com.razie.pub.assets._
  15. import com.razie.pub.base._
  16. import com.razie.pub.base.data._
  17. import razie.assets._
  18. /** simplified asset management functionality
  19. *
  20. * @author razvanc
  21. */
  22. object Assets {
  23. //------------------------- XP shorthands for accessing assets
  24. def xpl (path:String) = XP[AssetBase] (path).xpl(XpAssetsSolver, null)
  25. def xpe (path:String) = XP[AssetBase] (path).xpe(XpAssetsSolver, null)
  26. def xpa (path:String) = XP[AssetBase] (path).xpa(XpAssetsSolver, null)
  27. def xpla (path:String) = XP[AssetBase] (path).xpla(XpAssetsSolver, null)
  28. /** add a managed asset instance. These assets do not need an inventory - will all use the proxy inventory
  29. *
  30. * @param ass the asset to be managed
  31. * @param meta - the meta
  32. */
  33. def manage(ass:AssetBase, m:String):Unit = manage (ass, new Meta(new ActionItem(m), null, null, null, null))
  34. /** add a managed asset instance. These assets do not need an inventory - will all use the proxy inventory
  35. *
  36. * @param ass the asset to be managed
  37. * @param meta - the meta
  38. */
  39. def manage(ass:AssetBase, m:Meta):Unit = manage (ass, new MetaSpec(m))
  40. /** add a managed asset instance. These assets do not need an inventory - will all use the proxy inventory
  41. *
  42. * @param ass the asset to be managed
  43. * @param meta - optionally, the meta - if not passed in, the asset must be tagged with SoaAsset with a valid meta
  44. */
  45. def managejj(ass:AssetBase):Unit = manage(ass)
  46. def manage(ass:AssetBase , m:MetaSpec*):Unit = {
  47. // if (! InventoryAssetMgr.instance().hasInventory (ass.getKey.getType)) {
  48. val ms = if (m.length > 0) m(0) else ass.asInstanceOf[HasMeta].metaSpec
  49. // val inv =
  50. // if (InventoryAssetMgr.instance().hasInventory (ass.getKey.getType))
  51. // InventoryAssetMgr.instance().findInventory(ass.getKey().getType())
  52. // else null
  53. // if (ass.getClass.getAnnotation(classOf[SoaAsset]) != null)
  54. // ass.getClass.getAnnotation(classOf[SoaAsset]).asInstanceOf[SoaAsset].bindings.foreach ( _ match {
  55. // //TODO should i bind them all by default? use bindings just to restrict binding if needed?
  56. // case "http" =>
  57. // if (AgentHttpService.instance()!=null)
  58. // AgentHttpService.registerSoaAsset(ass.getClass, ms.meta)
  59. // })
  60. ms.meta.inventory = classOf[ProxyInventory].getName();
  61. // razie.Metas.add(ms)
  62. imanageClass (ass.getClass, ms)
  63. // }
  64. InventoryAssetMgr.instance().proxyInventory().register(ass.getKey(), ass);
  65. }
  66. // TODO niceify with an implicit manifest
  67. def manageClass[A](implicit m:scala.reflect.Manifest[A]) :Unit = {
  68. val cls = m.erasure
  69. if (cls.getAnnotation(classOf[SoaAsset]) == null)
  70. throw new IllegalArgumentException ("aset classes need annotated with SoaAsset")
  71. if (cls.getAnnotation(classOf[AssetMeta]) == null)
  72. throw new IllegalArgumentException ("aset classes need annotated with SoaAsset")
  73. val soaa = cls.getAnnotation(classOf[SoaAsset]).asInstanceOf[SoaAsset]
  74. val name = soaa.meta
  75. // if the inventory is present, it's already registered...will skip
  76. if (! InventoryAssetMgr.instance().hasInventory (name)) {
  77. val m = Meta.fromAnn (cls)
  78. val ms = new MetaSpec (m)
  79. // TODO add assocs from @AssotAssoc
  80. imanageClass (cls, ms)
  81. }
  82. }
  83. def imanageClass(cls:Class[_], ms:MetaSpec):Unit = {
  84. val name = ms.meta .id .name
  85. // if the inventory is present, it's already registered...will skip
  86. // if (! InventoryAssetMgr.instance().hasInventory (name)) {
  87. if (cls.getAnnotation(classOf[SoaAsset]) != null)
  88. cls.getAnnotation(classOf[SoaAsset]).asInstanceOf[SoaAsset].bindings.foreach ( _ match {
  89. //TODO should i bind them all by default? use bindings just to restrict binding if needed?
  90. case "http" =>
  91. if (AgentHttpService.instance()!=null)
  92. AgentHttpService.registerSoaAsset(cls, ms.meta)
  93. })
  94. razie.Metas.add(ms)
  95. // }
  96. }
  97. // ------------------------ associations
  98. /** create an instance association between the two. These instances are kept in sync with the entities
  99. *
  100. * @param a from
  101. * @param b to
  102. * @param ma association type
  103. */
  104. def associate (a:AssetKey, b:AssetKey, ma:MetaAssoc*):Unit =
  105. associate (Asset.apply(a), Asset.apply(b), ma:_*)
  106. def associate (a:AssetBase, b:AssetBase, ma:MetaAssoc*):Unit =
  107. AssetAssocs.associate (a,b,ma:_*)
  108. }
  109. /** asset association management
  110. *
  111. * @author razvanc
  112. */
  113. object AssetAssocs {
  114. /** creates an instance association between the two assets.
  115. * @parm a
  116. * @parm z
  117. * @parm ma - the type of association. If not given, will look it up in metas
  118. */
  119. def associate (a:AssetBase, b:AssetBase, ma:MetaAssoc*):Unit = {
  120. // TODO keep in sync- register with inventory and delte assocs or cascade or exception
  121. val mas = if (ma.size > 0) ma.head else {
  122. // TODO not both ways, just one way - between is both ways
  123. val temp = Metas.assocsBetween(a.getKey.meta, b.getKey.meta)
  124. require (temp.size == 1)
  125. temp.head
  126. }
  127. require (mas.aEnd == a.getKey.meta && mas.zEnd == b.getKey.meta)
  128. assocs += ((Asset.apply(a), Asset.apply(b), mas))
  129. }
  130. // TODO 2-2 add inventory of associations
  131. // TODO 2-2 add remote discovery of associations between remote entities
  132. /** find associated assets to the given key, both ways - browse only the given type
  133. *
  134. * @param key the key to start from
  135. * @param a - oiptional, an asset object to reflect
  136. * @param ma - the association type to follow
  137. * */
  138. protected def iassociated(key:AssetKey, a:Referenceable, ma:MetaAssoc):List[AssetBase] = {
  139. val ret = if (ma.aEnd == key.meta)
  140. assocs.filter (x => x._1.key == key && x._3 == ma).map (_._2.resolveIfLocal.asInstanceOf[AssetBase])
  141. else
  142. assocs.filter (x => x._2.key == key && x._3 == ma).map (_._1.resolveIfLocal.asInstanceOf[AssetBase])
  143. if (ret.isEmpty && key.aloc.isLocal) {
  144. // try reflection of associations - only for local assets
  145. val reala = if (a!= null) {
  146. if (a.isInstanceOf[AssetHandle])
  147. a.asInstanceOf[AssetHandle].resolve
  148. else a
  149. }
  150. else
  151. Asset.apply(key).resolve
  152. val methods = if (ma.aEnd == key.meta)
  153. reala.getClass.getMethods.filter (_.getName==ma.zRole)
  154. else
  155. reala.getClass.getMethods.filter (_.getName==ma.aRole)
  156. methods.headOption match {
  157. case Some(method) => method.invoke (reala) match {
  158. case l:List[AssetBase] => l
  159. case a:AssetBase => List(a)
  160. case _ => ret.toList
  161. }
  162. case _ => ret.toList
  163. }
  164. } else
  165. ret.toList
  166. }
  167. // TODO 2-2 add inventory of associations
  168. // TODO 2-2 add remote discovery of associations between remote entities
  169. /** find associated assets to the given key, both ways - browse only the given type
  170. *
  171. * @param key the key to start from
  172. * @param ma - the association type to follow
  173. * */
  174. def associated(key:AssetKey, ma:MetaAssoc) =
  175. iassociated (key, null, ma)
  176. /** find associated assets to the given key, both ways - browse only the given type
  177. *
  178. * @param a - an asset object to reflect
  179. * @param ma - the association type to follow
  180. * */
  181. def associated (a:AssetBase, ma:MetaAssoc) =
  182. iassociated(a.getKey, a, ma)
  183. // associatedKeys (a.getKey, ma).map (Asset.apply(_).resolve)
  184. /** find keys of associated assets to the given key, both ways - browse only the given type
  185. *
  186. * @param key the key to start from
  187. * @param ma - the association type to follow
  188. * */
  189. def associatedKeys (k:AssetKey, ma:MetaAssoc) = iassociated(k, null, ma).map (_.getKey)
  190. // TODO 3-2 optimize - index by key or something
  191. def assocs = assocsns.get
  192. private val assocsns = new razie.NoStatic[ListBuffer[(AssetHandle, AssetHandle, MetaAssoc)]] ("Assets.Assocs" ,
  193. {new ListBuffer[(AssetHandle, AssetHandle, MetaAssoc)] ()} )
  194. // def assocs : TAssocs = com.razie.pub.base.NoStaticS.get[TAssocs] match {
  195. // case Some (l) => l
  196. // case None => com.razie.pub.base.NoStaticS.put (new TAssocs ())
  197. // }
  198. //
  199. // private type TAssocs = ListBuffer[(AssetKey, AssetKey, MetaAssoc)]
  200. }