Package nexj.core.meta

Source Code of nexj.core.meta.ClassAspect

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

import java.util.Arrays;
import java.util.Iterator;

import nexj.core.meta.persistence.DataSource;
import nexj.core.meta.persistence.PersistenceMapping;
import nexj.core.util.ExceptionHolder;
import nexj.core.util.HashTab;
import nexj.core.util.Lookup;
import nexj.core.util.Named;
import nexj.core.util.UncheckedException;

/**
* Metaclass aspect.
* Derived from Metaclass for simplicity, to avoid
* creating multiple hierarchies for the related classes.
*/
public final class ClassAspect extends Metaclass implements Aspect
{
   // associations

   /**
    * The metaclass aspect helper.
    */
   protected ClassAspectHelper m_aspectHelper = new ClassAspectHelper(this);

   /**
    * Data source to persistence mapping map: PersistenceMapping[DataSource].
    */
   protected Lookup m_persistenceMappingMap = new HashTab(2);

   // constructors

   /**
    * Constructs the aspect.
    * @param sName The aspect name.
    */
   public ClassAspect(String sName)
   {
      super(sName);
   }

   // operations

   /**
    * Adds a new persistence mapping to the aspect.
    * @param persistenceMapping The persistence mapping to add.
    * @throws MetadataException if a persistence mapping
    * with the same data source already exists.
    */
   public void addPersistenceMapping(PersistenceMapping persistenceMapping)
   {
      verifyNotReadOnly();

      Object oldPersistenceMapping = m_persistenceMappingMap.put(
         persistenceMapping.getDataSource(), persistenceMapping);

      if (oldPersistenceMapping != null)
      {
         m_persistenceMappingMap.put(persistenceMapping.getDataSource(), oldPersistenceMapping);

         throw new MetadataException("err.meta.persistenceMappingDup",
            new Object[]
            {
               persistenceMapping.getDataSource().getName(),
               getName()
            });
      }

      persistenceMapping.setMetaclass(this);
   }

   /**
    * Gets a persistence mapping by data source.
    * @param dataSource The persistence mapping data source.
    * @return The persistence mapping object.
    * @throws MetadataLookupException if the persistence mapping does not exist.
    */
   public PersistenceMapping getPersistenceMapping(DataSource dataSource)
   {
      PersistenceMapping persistenceMapping = (PersistenceMapping)m_persistenceMappingMap.get(dataSource);

      if (persistenceMapping != null)
      {
         return persistenceMapping;
      }

      throw new MetadataLookupException("err.meta.persistenceMappingLookup", dataSource.getName(), this);
   }

   /**
    * Finds a persistence mapping by data source.
    * @param dataSource The persistence mapping data source.
    * @return The persistence mapping object, or null if not found.
    */
   public PersistenceMapping findPersistenceMapping(DataSource dataSource)
   {
      return (PersistenceMapping)m_persistenceMappingMap.get(dataSource);
   }

   /**
    * @return The persistence mapping count.
    */
   public int getPersistenceMappingCount()
   {
      return m_persistenceMappingMap.size();
   }

   /**
    * @return An iterator for the contained persistence mapping objects.
    */
   public Iterator getPersistenceMappingIterator()
   {
      return m_persistenceMappingMap.valueIterator();
   }

   /**
    * @see nexj.core.meta.Aspect#isAspect()
    */
   public boolean isAspect()
   {
      return true;
   }

   /**
    * @see nexj.core.meta.Aspect#addPointcutPattern(java.lang.String, boolean)
    */
   public void addPointcutPattern(String sPattern, boolean bInclusive)
   {
      verifyNotReadOnly();
      m_aspectHelper.addPointcutPattern(sPattern, bInclusive);
   }

   /**
    * @see nexj.core.meta.Aspect#getPointcutPattern(int)
    */
   public String getPointcutPattern(int nOrdinal)
   {
      return m_aspectHelper.getPointcutPattern(nOrdinal);
   }

   /**
    * @see nexj.core.meta.Aspect#isPointcutPatternInclusive(int)
    */
   public boolean isPointcutPatternInclusive(int nOrdinal)
   {
      return m_aspectHelper.isPointcutPatternInclusive(nOrdinal);
   }

   /**
    * @see nexj.core.meta.Aspect#getPointcutPatternCount()
    */
   public int getPointcutPatternCount()
   {
      return m_aspectHelper.getPointcutPatternCount();
   }

   /**
    * @see nexj.core.meta.Aspect#isMatching(nexj.core.meta.Pointcut)
    */
   public boolean isMatching(Pointcut pointcut)
   {
      return m_aspectHelper.isMatching(pointcut);
   }

   /**
    * @see nexj.core.meta.Aspect#addTo(nexj.core.meta.Pointcut)
    */
   public void addTo(Pointcut pointcut)
   {
      m_aspectHelper.addTo(pointcut);
   }

   /**
    * @see nexj.core.meta.Aspect#applyTo(nexj.core.meta.Pointcut, int)
    */
   public void applyTo(Pointcut pointcut, int nPass) throws MetadataException
   {
      throw new UnsupportedOperationException();
   }

   /**
    * @see nexj.core.meta.Aspect#removeFrom(nexj.core.meta.Pointcut)
    */
   public boolean removeFrom(Pointcut pointcut)
   {
      throw new UnsupportedOperationException();
   }

   /**
    * @see nexj.core.meta.Metaclass#setNextAction(nexj.core.meta.Action, java.lang.String)
    */
   public void setNextAction(Action action, String sName)
   {
      Action nextAction = action.getEvent().findAction(sName);

      if (nextAction == null)
      {
         nextAction = new Action(sName);
         nextAction.setEvent(action.getEvent());
      }

      action.setNextAction(nextAction);
   }

   /**
    * @see nexj.core.meta.Metaclass#resolveInheritance(nexj.core.util.ExceptionHolder)
    */
   protected ExceptionHolder resolveInheritance(ExceptionHolder eh)
   {
      verifyNotReadOnly();

      return super.resolveInheritance(applyAspects(eh));
   }

   /**
    * @see nexj.core.meta.Metaclass#completeAttributeDerivation(nexj.core.meta.Attribute, nexj.core.meta.Attribute)
    */
   protected void completeAttributeDerivation(Attribute derived, Attribute base)
   {
      derived.setOrdinal(-1);
      derived.setDeclarator(derived.getMetaclass());
   }

   /**
    * @see nexj.core.meta.Metaclass#completeEventDerivation(nexj.core.meta.Event, nexj.core.meta.Event)
    */
   protected void completeEventDerivation(Event derived, Event base)
   {
      derived.setDeclarator(derived.getMetaclass());
   }

   /**
    * @see nexj.core.meta.Metaclass#resolveAspectMembers(nexj.core.util.ExceptionHolder)
    */
   protected ExceptionHolder resolveAspectMembers(ExceptionHolder eh)
   {
      eh = super.resolveAspectMembers(eh);

      for (int i = 0, n = getEventCount(); i < n; ++i)
      {
         Event event = getEvent(i);

         event.resolveActions();
         event.sortActions();
      }

      return eh;
   }

   /**
    * Resolves the class aspects in the metadata.
    * @param metadata The root metadata object.
    * @return The topologically sorted aspect array.
    * @throws MetadataException if an error occurs.
    */
   public static ClassAspect[] resolveAspects(final Metadata metadata) throws MetadataException
   {
      // Sort topologically the aspects, the least dependency distance
      // first, and then by name within the aspects with the same distance

      ClassAspect[] aspectArray = new ClassAspect[metadata.getClassAspectCount()];
      Lookup predCountMap = new HashTab(metadata.getClassAspectCount());
      int nStart = 0;
      int nEnd = 0;

      for (Iterator itr = metadata.getClassAspectIterator(); itr.hasNext();)
      {
         ClassAspect aspect = (ClassAspect)itr.next();
         int nCount = aspect.getAspectCount();

         if (nCount == 0)
         {
            aspectArray[nEnd++] = aspect;
         }
         else
         {
            predCountMap.put(aspect, Primitive.createInteger(nCount));
         }
      }

      while (nStart < nEnd)
      {
         Arrays.sort(aspectArray, nStart, nEnd, Named.COMPARATOR);

         int nNewEnd;

         for (nNewEnd = nEnd; nStart < nEnd; ++nStart)
         {
            ClassAspect aspect = aspectArray[nStart];

            for (Iterator itr = metadata.getClassAspectIterator(); itr.hasNext();)
            {
               ClassAspect successor = (ClassAspect)itr.next();

               if (successor.hasAspect(aspect))
               {
                  Integer predCount = (Integer)predCountMap.get(successor);

                  if (predCount != null)
                  {
                     int nPredCount = predCount.intValue();

                     if (--nPredCount == 0)
                     {
                        predCountMap.remove(successor);
                        aspectArray[nNewEnd++] = successor;
                     }
                     else
                     {
                        predCountMap.put(successor, Primitive.createInteger(nPredCount));
                     }
                  }
               }
            }
         }

         nEnd = nNewEnd;
      }

      ExceptionHolder eh = null;

      if (predCountMap.size() != 0)
      {
         for (Iterator itr = predCountMap.iterator(); itr.hasNext();)
         {
            ClassAspect aspect = (ClassAspect)itr.next();
            MetadataValidationException e = new MetadataValidationException("err.meta.classAspectCircularDep",
               new Object[]{aspect.getName()});

            aspect.setProperties(e);
            eh = addException(eh, e);
         }
      }

      if (eh != null)
      {
         throw (MetadataException)eh;
      }

      // Resolve the aspect inheritance

      for (int i = 0; i < nEnd; ++i)
      {
         eh = aspectArray[i].resolveInheritance(eh);
      }

      if (eh != null)
      {
         throw (MetadataException)eh;
      }

      if (nEnd == aspectArray.length)
      {
         return aspectArray;
      }

      ClassAspect[] aspects = new ClassAspect[nEnd];

      System.arraycopy(aspectArray, 0, aspects, 0, nEnd);

      return aspects;
   }

   /**
    * Resolves the class aspect members.
    * @param aspects The topologically sorted aspect array (from resolveAspects())
    * @throws MetadataException if an error occurs.
    */
   public static void resolveMembers(ClassAspect[] aspects) throws MetadataException
   {
      ExceptionHolder eh = null;

      for (int i = 0; i < aspects.length; ++i)
      {
         eh = aspects[i].resolveAspectMembers(eh);
      }

      if (eh != null)
      {
         throw (MetadataException)eh;
      }
   }
  
   /**
    * Resolves the class aspect persistence.
    * @param aspects The topologically sorted aspect array (from resolveAspects())
    * @throws MetadataException if an error occurs.
    */
   public static void resolvePersistence(ClassAspect[] aspects) throws MetadataException
   {
      ExceptionHolder eh = null;

      for (int i = 0; i < aspects.length; ++i)
      {
         ClassAspect aspect = aspects[i];

         for (int k = 0, n = aspect.getAspectCount(); k < n; ++k)
         {
            ClassAspect base = (ClassAspect)aspect.getAspect(k);

            for (Iterator itr = base.getPersistenceMappingIterator(); itr.hasNext();)
            {
               PersistenceMapping baseMapping = (PersistenceMapping)itr.next();

               if (aspect.findPersistenceMapping(baseMapping.getDataSource()) == null)
               {
                  PersistenceMapping mapping = baseMapping.create();

                  mapping.setMetaclass(aspect);
                  mapping.setDataSource(baseMapping.getDataSource());

                  aspect.addPersistenceMapping(mapping);
               }
            }
         }

         for (Iterator itr = aspect.getPersistenceMappingIterator(); itr.hasNext();)
         {
            PersistenceMapping mapping = (PersistenceMapping)itr.next();

            try
            {
               mapping.resolveInheritance();
            }
            catch (MetadataValidationException e)
            {
               eh = addException(eh, e);
            }
            catch (UncheckedException e)
            {
               MetadataValidationException x = new MetadataValidationException(e);

               mapping.setProperties(x);
               eh = addException(eh, x);
            }
         }
      }

      if (eh != null)
      {
         throw (MetadataException)eh;
      }
   }

   // inner classes

   /**
    * Metaclass-specific aspect helper.
    */
   protected final static class ClassAspectHelper extends AspectHelper
   {
      protected ClassAspect m_aspect;

      public ClassAspectHelper(ClassAspect aspect)
      {
         m_aspect = aspect;
      }

      /**
       * @see nexj.core.meta.AspectHelper#getContainer()
       */
      protected Aspect getContainer()
      {
         return m_aspect;
      }
   }
}
TOP

Related Classes of nexj.core.meta.ClassAspect

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.