PageRenderTime 51ms CodeModel.GetById 15ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 1ms

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