Package nexj.core.persistence

Source Code of nexj.core.persistence.GenericPersistenceAdapter

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

import java.util.List;

import nexj.core.meta.Attribute;
import nexj.core.meta.Metaclass;
import nexj.core.meta.persistence.AttributeMapping;
import nexj.core.meta.persistence.ClassMapping;
import nexj.core.meta.persistence.Key;
import nexj.core.meta.persistence.PersistenceMapping;
import nexj.core.persistence.operator.ConversionMapper;
import nexj.core.runtime.Instance;
import nexj.core.runtime.InstanceList;
import nexj.core.runtime.InvocationContext;
import nexj.core.runtime.InvocationContextAware;
import nexj.core.runtime.InvocationContextHolder;
import nexj.core.runtime.ResourceManager;
import nexj.core.runtime.UnitOfWork;
import nexj.core.util.ObjUtil;
import nexj.core.util.Undefined;

/**
* Generic persistence adapter implementation.
*/
public abstract class GenericPersistenceAdapter implements PersistenceAdapter, InvocationContextAware, InvocationContextHolder, ResourceManager
{
   // attributes

   /**
    * The fragmented data source flag.
    */
   protected boolean m_bFragmented;

   // associations

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

   // operations

   /**
    * Sets the fragmented data source flag.
    * @param bFragmented The fragmented data source flag to set.
    */
   public void setFragmented(boolean bFragmented)
   {
      m_bFragmented = bFragmented;
   }

   /**
    * @return The fragmented data source flag.
    */
   public boolean isFragmented()
   {
      return m_bFragmented;
   }

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

   /**
    * @see nexj.core.runtime.InvocationContextHolder#getInvocationContext()
    */
   public InvocationContext getInvocationContext()
   {
      return m_context;
   }

   /**
    * @see nexj.core.persistence.PersistenceAdapter#read(nexj.core.persistence.Query)
    */
   public InstanceList read(Query query) throws PersistenceException
   {
      Cursor cursor = openCursor(query);

      try
      {
         return cursor.next(-1);
      }
      finally
      {
         cursor.close();
      }
   }

   /**
    * It is always safe to return false; however, doing so will impact the ability of the
    * framework to perform certain optimizations.
    * @see nexj.core.persistence.PersistenceAdapter#isUnique(nexj.core.persistence.Query, java.util.List)
    */
   public boolean isUnique(Query query, List sourceList)
   {
      return false;
   }

   /**
    * @see nexj.core.persistence.PersistenceAdapter#isSupported(nexj.core.persistence.Operator, int)
    */
   public boolean isSupported(Operator op, int nFlags)
   {
      return (nFlags & Operator.NORMALIZE_EXPRESSION) == Operator.NORMALIZE_WHERE;
   }

   /**
    * @see nexj.core.persistence.PersistenceAdapter#getConversionMapper()
    */
   public ConversionMapper getConversionMapper() throws PersistenceException
   {
      return Operator.getConversionMapper();
   }

   /**
    * This is the correct implementation for adapters where denormalization is not supported.
    * @see nexj.core.persistence.PersistenceAdapter#getQuery(nexj.core.persistence.Source)
    */
   public Query getQuery(Source source)
   {
      return source.getQuery();
   }

   /**
    * Adds an extension work item for a primitive attribute.
    * @param uow The unit of work.
    * @param instance The instance.
    * @param primaryWork The primary work item.
    * @param attributeMapping The primitive attribute mapping.
    * @param value The value to set.
    * @return The work item for the primitive attribute.
    */
   protected Work addPrimitiveWork(UnitOfWork uow, Instance instance,
      Work primaryWork, AttributeMapping attributeMapping, Object value)
   {
      return primaryWork;
   }

   /**
    * Adds an extension work item for an association.
    * @param uow The unit of work.
    * @param instance The instance.
    * @param primaryWork The primary work item.
    * @param assocMapping The association mapping.
    * @return The work item for the association.
    */
   protected Work addClassWork(UnitOfWork uow, Instance instance,
      Work primaryWork, ClassMapping assocMapping)
   {
      return primaryWork;
   }

   /**
    * Determines whether to add successors or predecessors to the create work item.
    * @param work The create work item.
    * @param assocMapping The mapping on the association attribute.
    * @param bOID True if the instance being created has an object key; false otherwise.
    * @return True to add successors to the work item; false to add predecessors.
    */
   protected boolean isCreateSuccessor(Work work, ClassMapping assocMapping, boolean bOID)
   {
      return assocMapping.getKey(false).isObjectKeyPart();
   }

   /**
    * Adds create dependencies for the work item.
    * @param uow The unit of work.
    * @param instance The instance being created.
    * @param primaryWork The work item for which to add the dependencies.
    */
   protected void addCreateDependencies(UnitOfWork uow, Instance instance, Work primaryWork)
   {
      boolean bOID = (instance.getOID() != null);
      Metaclass metaclass = instance.getMetaclass();
      PersistenceMapping mapping = instance.getPersistenceMapping();

      for (int i = 0, nCount = metaclass.getInstanceAttributeCount(); i < nCount; ++i)
      {
         Attribute attribute = metaclass.getInstanceAttribute(i);
         AttributeMapping attributeMapping = mapping.getAttributeMapping(attribute);

         if (attributeMapping == null)
         {
            continue;
         }

         Object value = instance.getValueDirect(i);

         // The value cannot be undefined, the Instance.validate() has taken care of that.

         if (attribute.getType().isPrimitive())
         {
            addPrimitiveWork(uow, instance, primaryWork, attributeMapping, value);
         }
         else
         {
            InstanceList list = null;
            Instance inst = null;
            boolean bNull;

            if (attribute.isCollection())
            {
               list = (InstanceList)value;
               bNull = (list == null || list.isEmpty());
            }
            else
            {
               inst = (Instance)value;
               bNull = (inst == null);
            }

            if (!bNull)
            {
               // TODO: Insert with composition mappings.
               ClassMapping assocMapping = (ClassMapping)attributeMapping;
               boolean bSuccessor = isCreateSuccessor(primaryWork, assocMapping, bOID);

               if (bSuccessor)
               {
                  if (list == null)
                  {
                     inst.getAdapter().addDependency(uow, primaryWork, inst,
                        assocMapping.getKey(true), assocMapping.getKey(false), true);
                  }
                  else
                  {
                     for (int k = 0; k < list.getCount(); ++k)
                     {
                        inst = list.getInstance(k);

                        if (inst != null)
                        {
                           inst.getAdapter().addDependency(uow, primaryWork, inst,
                              assocMapping.getKey(true), assocMapping.getKey(false), true);
                        }
                     }
                  }
               }
               else
               {
                  Work work = addClassWork(uow, instance, primaryWork, assocMapping);

                  if (list != null)
                  {
                     inst = list.getInstance(0);
                  }

                  if (inst.getOID() != null)
                  {
                     work.setKeyValue(assocMapping.getKey(false), assocMapping.getKey(true), inst);

                     if (assocMapping.getKey(false) == mapping.getObjectKey())
                     {
                        instance.setOID(inst.getOID());
                     }
                  }
                  else
                  {
                     inst.getAdapter().addDependency(uow, work, inst,
                        assocMapping.getKey(false), assocMapping.getKey(true), false);
                  }
               }
            }
         }

         if (attributeMapping.isDenormalized())
         {
            uow.addDenorm(instance, attributeMapping);
         }
      }

      if (bOID)
      {
         for (int i = primaryWork.getSuccessorCount() - 1; i >= 0; --i)
         {
            primaryWork.getSuccessor(i).setKeyValue((Key)primaryWork.getSuccessorData(i), (Key)primaryWork.getSuccessorData2(i), instance);
         }

         primaryWork.removeAllSuccessors();
      }
   }

   /**
    * Adds update dependencies for the work item.
    * @param uow The unit of work.
    * @param instance The instance being updated.
    * @param primaryWork The work item for which to add the dependencies.
    */
   protected void addUpdateDependencies(UnitOfWork uow, Instance instance, Work primaryWork)
   {
      Metaclass metaclass = instance.getMetaclass();
      PersistenceMapping mapping = instance.getPersistenceMapping();

      for (int i = 0, nCount = metaclass.getInstanceAttributeCount(); i < nCount; ++i)
      {
         Attribute attribute = metaclass.getInstanceAttribute(i);
         AttributeMapping attributeMapping = mapping.getAttributeMapping(attribute);

         if (attributeMapping == null)
         {
            continue;
         }

         Object value = instance.getValueDirect(i);

         if (value == Undefined.VALUE || ObjUtil.equal(value, instance.getOldValueDirect(i)))
         {
            continue;
         }

         if (attribute.getType().isPrimitive())
         {
            addPrimitiveWork(uow, instance, primaryWork, attributeMapping, value);
         }
         else
         {
            InstanceList list = null;
            Instance inst = null;
            boolean bNull;

            if (attribute.isCollection())
            {
               list = (InstanceList)value;
               bNull = (list == null || list.isEmpty());
            }
            else
            {
               inst = (Instance)value;
               bNull = (inst == null);
            }

            ClassMapping assocMapping = (ClassMapping)attributeMapping;
            boolean bSuccessor;

            // TODO: Update composition mappings

            if (assocMapping.getKey(false).isObjectKey())
            {
               bSuccessor = true;
            }
            else if (assocMapping.getKey(true).isObjectKey())
            {
               bSuccessor = false;
            }
            else if (attribute.isCollection())
            {
               bSuccessor = true;
            }
            else
            {
               bSuccessor = false;
            }

            if (bSuccessor)
            {
               if (!bNull)
               {
                  if (list == null)
                  {
                     inst.getAdapter().addDependency(uow, primaryWork, inst,
                        assocMapping.getKey(true), assocMapping.getKey(false), true);
                  }
                  else
                  {
                     for (int k = 0; k < list.getCount(); ++k)
                     {
                        inst = list.getInstance(k);

                        if (inst != null)
                        {
                           inst.getAdapter().addDependency(uow, primaryWork, inst,
                              assocMapping.getKey(true), assocMapping.getKey(false), true);
                        }
                     }
                  }
               }
            }
            else
            {
               Work work = addClassWork(uow, instance, primaryWork, assocMapping);

               if (bNull)
               {
                  if (assocMapping.getKey(false) != mapping.getObjectKey())
                  {
                     work.setKeyValue(assocMapping.getKey(false), assocMapping.getKey(true), null);
                  }
               }
               else
               {
                  if (list != null)
                  {
                     inst = list.getInstance(0);
                  }

                  if (inst.getOID() != null)
                  {
                     if (assocMapping.getKey(false) != mapping.getObjectKey())
                     {
                        work.setKeyValue(assocMapping.getKey(false), assocMapping.getKey(true), inst);
                     }
                  }
                  else
                  {
                     inst.getAdapter().addDependency(uow, work, inst,
                        assocMapping.getKey(false), assocMapping.getKey(true), false);
                  }
               }
            }
         }

         if (attributeMapping.isDenormalized())
         {
            uow.addDenorm(instance, attributeMapping);
         }
      }
   }
}
TOP

Related Classes of nexj.core.persistence.GenericPersistenceAdapter

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.