Package nexj.core.runtime.sys

Source Code of nexj.core.runtime.sys.SysObject

// Copyright 2010 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.runtime.sys;

import nexj.core.meta.Event;
import nexj.core.meta.Metaclass;
import nexj.core.persistence.Cursor;
import nexj.core.persistence.OID;
import nexj.core.persistence.Query;
import nexj.core.runtime.ActionContext;
import nexj.core.runtime.Instance;
import nexj.core.runtime.InstanceList;
import nexj.core.runtime.InvocationContext;
import nexj.core.runtime.InvocationContextAware;
import nexj.core.scripting.Function;
import nexj.core.scripting.Pair;
import nexj.core.scripting.Symbol;
import nexj.core.util.HashTab;
import nexj.core.util.Lookup;
import nexj.core.util.Lookup2D;

/**
* Implements the system object methods.
*/
public class SysObject implements InvocationContextAware
{
   // associations

   /**
    * The invocation context.
    */
   protected InvocationContext m_context;

   // operations

   /**
    * @see nexj.core.runtime.InvocationContextAware#setInvocationContext(nexj.core.runtime.InvocationContext)
    */
   public void setInvocationContext(InvocationContext context)
   {
      m_context = context;
   }

   /**
    * The system read event main action.
    * read(class, attributes, where, orderBy, count, offset, xlock)
    */
   public InstanceList read(Metaclass metaclass, Pair attributes, Object where, Pair orderBy,
      Number count, Number offset, Boolean xlock, ActionContext actx)
   {
      return Query.createRead(metaclass, attributes, where, orderBy,
         (count == null) ? -1 : count.intValue(),
         (offset == null) ? 0 : offset.intValue(),
         (xlock == null) ? false : xlock.booleanValue(),
         Query.SEC_DEFAULT, m_context).read();
   }

   /**
    * The system aggregate event main action.
    * aggregate(class, attributes, where, groupBy, having, orderBy, count, offset)
    */
   public InstanceList aggregate(Metaclass metaclass, Pair attributes, Object where, Pair groupBy,
      Object having, Pair orderBy, Number count, Number offset, ActionContext actx)
   {
      return Query.createAggregate(metaclass, attributes, where, groupBy, having, orderBy,
         (count == null) ? -1 : count.intValue(),
         (offset == null) ? 0 : offset.intValue(),
         Query.SEC_DEFAULT, m_context).read();
   }

   /**
    * The system openCursor event main action.
    * openCursor(class, attributes, where, orderBy, count, offset, xlock)
    */
   public Cursor openCursor(Metaclass metaclass, Pair attributes, Object where, Pair orderBy,
      Number count, Number offset, Boolean xlock, ActionContext actx)
   {
      return Query.createRead(metaclass, attributes, where, orderBy,
         (count == null) ? -1 : count.intValue(),
         (offset == null) ? 0 : offset.intValue(),
         (xlock == null) ? false : xlock.booleanValue(),
         Query.SEC_DEFAULT, m_context).openCursor();
   }

   /**
    * The system openAggregateCursor event main action.
    * openAggregateCursor(class, attributes, where, groupBy, having, orderBy, count, offset)
    */
   public Cursor openAggregateCursor(Metaclass metaclass, Pair attributes, Object where, Pair groupBy,
      Object having, Pair orderBy, Number count, Number offset, ActionContext actx)
   {
      return Query.createAggregate(metaclass, attributes, where, groupBy, having, orderBy,
         (count == null) ? -1 : count.intValue(),
         (offset == null) ? 0 : offset.intValue(),
         Query.SEC_DEFAULT, m_context).openCursor();
   }

   /**
    * The system load event aroundLoad action.
    */
   public void aroundLoad(Instance instance, Pair attributes, ActionContext actx)
   {
      try
      {
         instance.setLoading(true);

         // If the load event has been overridden, provide a simple form of the associations as well
         if (actx.getAction().getEvent().getDeclarator().getBase() != null)
         {
            for (Pair pair = attributes, prev = null; pair != null; pair = pair.getNext())
            {
               if (pair.getHead() instanceof Pair)
               {
                  Pair assoc = (Pair)pair.getHead();

                  if (assoc.getHead() == Symbol.ATAT)
                  {
                     assoc = assoc.getNext();

                     if (instance.getMetaclass().getMetadata().getMetaclass
                        (((Symbol)assoc.getHead()).getName()).isUpcast(instance.getMetaclass()))
                     {
                        pair.setHead(null);
                       
                        for (assoc = assoc.getNext(); assoc != null; assoc = assoc.getNext())
                        {
                           if (pair.getHead() == null)
                           {
                              pair.setHead(assoc.getHead());
                           }
                           else
                           {
                              Pair copy = new Pair(assoc.getHead(), pair.getTail());
                             
                              pair.setTail(copy);
                              pair = copy;
                           }
                        }

                        if (pair.getHead() != null)
                        {
                           prev = pair;
                           continue;
                        }
                     }

                     if (prev == null)
                     {
                        attributes = pair.getNext();
                     }
                     else
                     {
                        prev.setTail(pair.getTail());
                     }

                     continue;
                  }

                  attributes = new Pair(assoc.getHead(), attributes);
               }

               prev = pair;
            }

            actx.setArg(0, attributes);
         }

         actx.callNext();
      }
      finally
      {
         instance.setLoading(false);
      }
   }

   /**
    * The system load event main action.
    * load(this, attributes)
    */
   public void load(Instance instance, Pair attributes, ActionContext actx)
   {
      actx.setArg(0, instance.load(attributes));
   }

   /**
    * The system new event main action.
    * new(class, values)
    */
   public Instance newInstance(Metaclass metaclass, Pair values, ActionContext actx)
   {
      Instance instance = new Instance(metaclass, m_context);

      instance.setNew();

      for (; values != null; values = values.getNext())
      {
         Pair pair = (Pair)values.getHead();
         Symbol sym = (Symbol)pair.getHead();

         if (sym == Symbol._OID)
         {
            instance.setOID((OID)pair.getTail());
         }
         else
         {
            instance.setValue(sym.getName(), pair.getTail());
         }
      }

      ((Event)metaclass.getSelector("create").getMember(0)).invoke(instance, (Object[])null, m_context.getMachine());

      return instance;
   }

   /**
    * The system create event main action.
    * isNew(obj)
    */
   public boolean isNew(Instance instance, ActionContext actx)
   {
      return instance.getState() == Instance.NEW;
   }

   /**
    * The system create event main action.
    * create(obj)
    */
   public void create(Instance instance, ActionContext actx)
   {
      instance.setEventInvoked(true);
   }

   /**
    * The system update event main action.
    * update(obj)
    */
   public void update(Instance instance, ActionContext actx)
   {
      switch (instance.getState())
      {
         case Instance.NEW:
            if (!instance.isEventInvoked())
            {
               break;
            }

         case Instance.INIT:
         case Instance.CLEAN:
         case Instance.DIRTY:
            instance.setDirty();
            instance.setEventInvoked(true);
            break;
      }
   }

   /**
    * The system create event main action.
    * delete(obj)
    */
   public void delete(Instance instance, ActionContext actx)
   {
      instance.delete();
      instance.replicate();
   }

   /**
    * Invokes cascade delete logic on related objects.
    */
   public void deleteRelated(Instance instance, ActionContext actx)
   {
      instance.deleteRelated();
   }

   /**
    * The system commit event main action.
    * commit(obj)
    */
   public void commit(Instance instance, ActionContext actx)
   {
      instance.setCommitPending(false);
      instance.replicate();
   }

   /**
    * The system lock event main action.
    * lock(obj)
    */
   public void lock(Instance instance, ActionContext actx)
   {
      instance.lock();
   }

   /**
    * Old event main action.
    * old(obj, attribute)
    * @see nexj.core.runtime.Instance#getOldValue(String)
    */
   public Object getOldValue(Instance instance, Symbol sym, ActionContext actx)
   {
      return instance.getOldValue(sym.getName());
   }

   /**
    * Pre event main action.
    * pre(obj, attribute)
    * @see nexj.core.runtime.Instance#getPreValue(String)
    */
   public Object getPreValue(Instance instance, Symbol sym, ActionContext actx)
   {
      return instance.getPreValue(sym.getName());
   }

   /**
    * isDirty event main action.
    * isDirty(obj, attribute)
    * Invokes Instance.isDirty(String).
    * @see nexj.core.runtime.Instance#isDirty(String)
    */
   public boolean isDirty(Instance instance, Symbol sym, ActionContext actx)
   {
      return instance.isDirty(sym.getName());
   }

   /**
    * isUpdated event main action.
    * isUpdated(obj, attribute)
    * Invokes Instance.isUpdated(String).
    * @see nexj.core.runtime.Instance#isUpdated(String)
    */
   public boolean isUpdated(Instance instance, Symbol sym, ActionContext actx)
   {
      return instance.isUpdated(sym.getName());
   }

   /**
    * annotation event main action.
    * Invokes Instance.setAnnotation(String, Object).
    * @see nexj.core.runtime.Instance#setAnnotation(String, Object)
    */
   public void setAnnotation(Instance instance, Symbol sym, Object value, ActionContext actx)
   {
      instance.setAnnotation(sym.getName(), value);
   }

   /**
    * annotation event main action.
    * Invokes Instance.findAnnotation(String, Object).
    * @see nexj.core.runtime.Instance#findAnnotation(String)
    */
   public Object getAnnotation(Instance instance, Symbol sym, ActionContext actx)
   {
      return instance.findAnnotation(sym.getName());
   }

   /**
    * Class event main action.
    * :class()
    * @return The metaclass.
    */
   public Metaclass getClass(Metaclass metaclass, ActionContext actx)
   {
      return metaclass;
   }

   /**
    * The OID event main action.
    * :oid()
    * @return The instance OID.
    */
   public OID getOID(Instance instance, ActionContext actx)
   {
      return instance.getOID();
   }
  
   /**
    * Invokes the rules engine.
    * invoke(instance, rulesetName, attribute, attributes)
    */
   public Object invokeRulesEngine(Metaclass metaclass, Instance instance, String sName, Symbol attribute, Pair attributes, ActionContext actx)
   {
      Lookup2D objMap = (Lookup2D)metaclass.getValue("objMap");
      Instance engine = (Instance)objMap.get(instance, sName);
      boolean bCreate = (engine == null);
     
      if (bCreate)
      {
         engine = getRulesEngine(metaclass, instance, sName);
         objMap.put(instance, sName, engine);
      }

      try
      {
         Object[] args = new Object[]{attribute};
         Object obj = engine.invoke("compute", args);
        
         for (; attributes != null; attributes = attributes.getNext())
         {
            args[0] = attributes.getHead();
            engine.invoke("compute", args);
         }

         return obj;
      }
      finally
      {
         if (bCreate)
         {
            objMap.remove(instance, sName);
         }
      }
   }

   /**
    * Creates a rule set cache key.
    * @param metaclass The rules engine metaclass.
    * @param sName The rule set name. 
    */
   protected Object createRuleSetKey(Metaclass metaclass, String sName)
   {
      return new Pair(metaclass.getSymbol(), sName);
   }

   /**
    * Gets the rules engine constructor from the cache or loads and compiles the rules.
    * @param metaclass The rules engine metaclass.
    * @param instance The instance for which to construct the rules engine.
    * @param sName The rule set name.
    * @return The rules engine instance.
    */
   protected Instance getRulesEngine(Metaclass metaclass, Instance instance, String sName)
   {
      Object key = m_context.getPartitionedKey(createRuleSetKey(metaclass, sName));
      Function constructor = (Function)m_context.getGlobalCache().get(key);

      if (constructor == null)
      {
         boolean bSecureSaved = m_context.isSecure();

         m_context.setSecure(false);

         try
         {
            Object rules = metaclass.invoke("loadRules", new Object[]{instance.getMetaclass(), sName});

            constructor = (Function)metaclass.invoke("compile", new Object[]{instance.getMetaclass(), sName, rules});

            Lookup map = new HashTab(1);

            map.put(key, constructor);
            m_context.getGlobalCache().update(null, map, m_context.getUnitOfWork().getTime());
         }
         finally
         {
            m_context.setSecure(bSecureSaved);
         }
      }

      return (Instance)m_context.getMachine().invoke(constructor, instance, (Object[])null);
   }

   /**
    * Invalidates the cached rules for a given rule set.
    * clearCache(rulesetName)
    * @param metaclass The rules engine metaclass.
    * @param sName The rule set name. 
    * @param actx The action context.
    */
   public void clearRulesCache(Metaclass metaclass, String sName, ActionContext actx)
   {
      m_context.getUnitOfWork().uncache(createRuleSetKey(metaclass, sName));
   }
}
TOP

Related Classes of nexj.core.runtime.sys.SysObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.