Package nexj.core.meta.persistence.virtual

Source Code of nexj.core.meta.persistence.virtual.XMLVirtualDataSourceMetadataLoader

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

import java.util.ArrayList;

import org.w3c.dom.Element;

import nexj.core.meta.Attribute;
import nexj.core.meta.Component;
import nexj.core.meta.Metaclass;
import nexj.core.meta.MetadataException;
import nexj.core.meta.MetadataValidationException;
import nexj.core.meta.Primitive;
import nexj.core.meta.persistence.AttributeMapping;
import nexj.core.meta.persistence.DataSource;
import nexj.core.meta.persistence.DataSourceType;
import nexj.core.meta.persistence.PersistenceMapping;
import nexj.core.meta.persistence.SchemaUpgrade;
import nexj.core.meta.persistence.XMLPersistenceMetadataLoader;
import nexj.core.meta.xml.XMLMetadata;
import nexj.core.meta.xml.XMLMetadataHelper;
import nexj.core.meta.xml.XMLMetadataHelper.ContextFixup;
import nexj.core.meta.xml.XMLMetadataLoader;
import nexj.core.scripting.Pair;
import nexj.core.scripting.Symbol;
import nexj.core.util.Lookup;
import nexj.core.util.XMLUtil;
import nexj.core.util.XMLUtil.ElementHandler;

/**
* Loads virtual persistence adapter data source, connection, and persistence mapping
* metadata.
*/
public class XMLVirtualDataSourceMetadataLoader implements XMLPersistenceMetadataLoader
{
   // associations

   /**
    * The metadata loader.
    */
   protected XMLMetadataLoader m_loader;

   /**
    * The metadata helper.
    */
   protected XMLMetadataHelper m_helper;

   // operations

   /**
    * @see nexj.core.meta.persistence.XMLPersistenceMetadataLoader#loadConnection(org.w3c.dom.Element, nexj.core.meta.persistence.DataSource, nexj.core.meta.xml.XMLMetadataLoader)
    */
   public void loadConnection(Element element, DataSource source, final XMLMetadataLoader loader)
   {
      final VirtualDataSource ds = (VirtualDataSource)source;
      final VirtualDataSourceFragment defaultFragment = (VirtualDataSourceFragment)ds.getDefaultFragment();
      Component adapter = new Component(ds.getName(), ds.getAdapter().getClassObject(), Component.CONTEXT);

      ds.setComponent(adapter);
      adapter.setMetadata(loader.getMetadata());

      if (element != null)
      {
         loadFragment(element, defaultFragment, loader);

         XMLUtil.withFirstChildElement(element, "Fragments", false, new ElementHandler()
         {
            public void handleElement(Element fragmentsElement)
            {
               XMLUtil.forEachChildElement(fragmentsElement, "Fragment", loader.getHelper().new ElementHandler("fragment")
               {
                  protected void handleElement(Element fragmentElement, String sName)
                  {
                     VirtualDataSourceFragment fragment = (VirtualDataSourceFragment)defaultFragment.clone(false);

                     fragment.setName(sName);
                     loadFragment(fragmentElement, fragment, loader);
                     ds.addFragment(fragment);
                  }
               });
            }
         });

         if (ds.getFragmentCount() > 1)
         {
            adapter.addPrimitivePropertyInitializer("fragmented", Boolean.TRUE);
         }
      }
      else
      {
         // Disable if no connection file entry.
         ds.setCreatable(false);
         ds.setReadable(false);
         ds.setUpdatable(false);
         ds.setDeletable(false);
         ds.setExecutable(false);
      }
   }

   /**
    * Loads fragment metadata.
    * @param element The fragment element.
    * @param fragment The fragment.
    * @param loader The metadata loader.
    */
   protected void loadFragment(Element element, VirtualDataSourceFragment fragment, XMLMetadataLoader loader)
   {
      fragment.setWarningTimeout(loader.getProperty("dataSourceConnection." + fragment.getDataSource().getName() +
         ".warningTimeout", XMLUtil.getLongAttr(element, "warningTimeout", fragment.getWarningTimeout())));

      loader.loadProperties(element, "Properties", fragment.getPropertyHolder());
   }

   /**
    * @see nexj.core.meta.persistence.XMLPersistenceMetadataLoader#loadDataSource(org.w3c.dom.Element, java.lang.String, nexj.core.meta.persistence.DataSourceType, nexj.core.meta.xml.XMLMetadataLoader)
    */
   public DataSource loadDataSource(Element element, String sName, DataSourceType type, XMLMetadataLoader loader)
   {
      VirtualDataSource ds = new VirtualDataSource(sName);

      ds.setType(type);
      loader.loadDataSource(element, ds);

      return ds;
   }

   /**
    * @see nexj.core.meta.persistence.XMLPersistenceMetadataLoader#loadMapping(org.w3c.dom.Element, nexj.core.meta.Metaclass, nexj.core.meta.persistence.DataSource, nexj.core.meta.xml.XMLMetadataLoader)
    */
   public PersistenceMapping loadMapping(Element element, final Metaclass metaclass, DataSource dataSource, final XMLMetadataLoader loader)
   {
      m_loader = loader;
      m_helper = loader.getHelper();

      final VirtualMapping mapping = new VirtualMapping();
      final XMLMetadata metadata = loader.getMetadata();
      final String sURLPrefix = "class:" + metaclass.getName() + ".persistence";
      int nCookie = m_helper.pushMarker(MetadataValidationException.TYPE_NAME, "ServiceMapping");

      m_helper.pushMarker("class", metaclass.getName());

      try
      {
         mapping.setMetaclass(metaclass);
         mapping.setDataSource(dataSource);

         XMLUtil.withFirstChildElement(element, "ServiceMapping",
            true, new XMLUtil.ElementHandler()
         {
            public void handleElement(Element element)
            {
               final ArrayList keyTypeList = new ArrayList(4);

               XMLUtil.withFirstChildElement(element, "KeyParts", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     XMLUtil.forEachChildElement(element, "KeyPart", new XMLUtil.ElementHandler()
                     {
                        public void handleElement(Element element)
                        {
                           keyTypeList.add(Primitive.find(XMLUtil.getReqStringAttr(element, "type")));

                           String sAttributeName = XMLUtil.getStringAttr(element, "attribute");

                           if (sAttributeName != null)
                           {
                              Attribute attribute = metaclass.getAttribute(sAttributeName);
                              VirtualPrimitiveMapping primitiveMapping = new VirtualPrimitiveMapping();

                              primitiveMapping.setObjectKeyPart(keyTypeList.size() - 1);
                              primitiveMapping.setAttribute(attribute);
                              mapping.addAttributeMapping(primitiveMapping);
                              primitiveMapping.validate(metadata, m_helper.getWarnings());
                           }
                        }
                     });

                     mapping.setKey((Primitive[])keyTypeList.toArray(new Primitive[keyTypeList.size()]));
                  }
               });

               XMLUtil.withFirstChildElement(element, "AttributeMappings", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     XMLUtil.forEachChildElement(element, "AttributeMapping", new XMLUtil.ElementHandler()
                     {
                        public void handleElement(Element element)
                        {
                           String sName = XMLUtil.getReqStringAttr(element, "name");
                           int nMaxLength = XMLUtil.getIntAttr(element, "maxLength", 0);
                           final Attribute attribute = metaclass.getAttribute(sName);
                           AttributeMapping attrMapping;

                           if (attribute.getType().isPrimitive())
                           {
                              VirtualPrimitiveMapping primitiveMapping = new VirtualPrimitiveMapping();

                              attrMapping = primitiveMapping;

                              if (element.hasAttribute("attributes"))
                              {
                                 throw new MetadataException("err.meta.persistence.virtual.invalidPropertySpecified",
                                    new Object[]{"attributes", sName, metaclass.getName()});
                              }

                              if (XMLUtil.getBooleanAttr(element, "objectSourceKey", false))
                              {
                                 throw new MetadataException("err.meta.persistence.virtual.invalidPropertySpecified",
                                    new Object[]{"objectSourceKey", sName, metaclass.getName()});
                              }

                              if (element.hasAttribute("destinationKey"))
                              {
                                 throw new MetadataException("err.meta.persistence.virtual.invalidPropertySpecified",
                                    new Object[]{"destinationKey", sName, metaclass.getName()});
                              }

                              if (nMaxLength != 0)
                              {
                                 if (attribute.getType() != Primitive.BINARY && attribute.getType() != Primitive.STRING)
                                 {
                                    throw new MetadataException("err.meta.persistence.virtual.maxLengthSpecified",
                                       new Object[]{attribute.getName(), metaclass.getName()});
                                 }

                                 primitiveMapping.setMaxLength(nMaxLength);
                              }
                           }
                           else
                           {
                              final VirtualClassMapping classMapping = new VirtualClassMapping();

                              attrMapping = classMapping;

                              classMapping.setComposition((Pair)m_helper.parse(
                                 XMLUtil.getStringAttr(element, "attributes"),
                                 true, null, null, metadata.getGlobalEnvironment()
                              ));

                              final boolean bObjectSourceKey = XMLUtil.getBooleanAttr(element, "objectSourceKey", false);
                              final String sDestinationKeyName = XMLUtil.getStringAttr(element, "destinationKey");

                              if (nMaxLength != 0)
                              {
                                 throw new MetadataException("err.meta.persistence.virtual.maxLengthSpecified",
                                    new Object[]{attribute.getName(), metaclass.getName()});
                              }

                              loader.addPersistenceMappingFixup(new ContextFixup(m_helper)
                              {
                                 public void fixup()
                                 {
                                    Metaclass type = (Metaclass)attribute.getType();
                                    PersistenceMapping assocClassMapping = type.getPersistenceMapping();

                                    if (assocClassMapping == null)
                                    {
                                       throw new MetadataException("err.meta.missingAssocPersistenceMapping",
                                          new Object[]{attribute.getName(), metaclass.getName(), type.getName()});
                                    }

                                    classMapping.setSourceKey((bObjectSourceKey) ? mapping.getObjectKey() : new VirtualKey(attribute));
                                    classMapping.setDestinationKey(assocClassMapping.addForeignKey(sDestinationKeyName, classMapping));
                                 }
                              });

                              loader.addComponentFixup(new ContextFixup(m_helper)
                              {
                                 public void fixup()
                                 {
                                    classMapping.validate(metadata, m_helper.getWarnings());
                                 }
                              });
                           }

                           attrMapping.setAttribute(attribute);
                           mapping.addAttributeMapping(attrMapping);
                        }
                     });
                  }
               });

               XMLUtil.withFirstChildElement(element, "SortKeys", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     XMLUtil.forEachChildElement(element, "SortKey", new XMLUtil.ElementHandler()
                     {
                        public void handleElement(Element element)
                        {
                           mapping.addSortKey(
                              (Pair)m_helper.parse(XMLUtil.getReqStringAttr(element, "attributes"), true,
                                 mapping.getTextPositionMap(), null, metadata.getGlobalEnvironment()),
                              XMLUtil.getBooleanAttr(element, "unique", false)
                           );
                        }
                     });
                  }
               });

               XMLUtil.withFirstChildElement(element, "ReadMapping", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     final ReadMapping readMapping = mapping.getReadMapping();

                     XMLUtil.forEachChildElement(element, "Case", new XMLUtil.ElementHandler()
                     {
                        private int m_nOrdinal = 0;

                        public void handleElement(Element element)
                        {
                           final String sReadPrefix = sURLPrefix + ".read." + m_nOrdinal;
                           Object whereExpr = m_helper.parse(
                              XMLUtil.getStringAttr(element, "where"),
                              false, sReadPrefix + "$where", mapping.getTextPositionMap(), Symbol.ELSE, metadata.getGlobalEnvironment()
                           );
                           Pair variables = (Pair)m_helper.parse(
                              XMLUtil.getStringAttr(element, "variables"),
                              true, mapping.getTextPositionMap(), null, metadata.getGlobalEnvironment()
                           );
                           final ReadMappingCase readMappingCase = new ReadMappingCase();

                           readMappingCase.setWhere(whereExpr);
                           readMappingCase.setVariables(variables);

                           XMLUtil.withFirstChildElement(element, "Read", true, new XMLUtil.ElementHandler()
                           {
                              public void handleElement(Element element)
                              {
                                 readMappingCase.setReadScript(loadScript(element, sReadPrefix + "$read", mapping.getTextPositionMap()));
                              }
                           });

                           XMLUtil.withFirstChildElement(element, "Close", false, new XMLUtil.ElementHandler()
                           {
                              public void handleElement(Element element)
                              {
                                 readMappingCase.setCloseScript(loadScript(element, sReadPrefix + "$close", mapping.getTextPositionMap()));
                              }
                           });

                           readMapping.addCase(readMappingCase);
                           m_nOrdinal += 1;
                        }
                     });
                  }
               });

               XMLUtil.withFirstChildElement(element, "CreateMapping", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     final WorkMapping operation = new WorkMapping(metaclass);

                     operation.setBatch(XMLUtil.getBooleanAttr(element, "batch", operation.isBatch()));
                     operation.setScript(loadScript(element, sURLPrefix + ".create", mapping.getTextPositionMap()));
                     mapping.setCreateMapping(operation);
                  }
               });

               XMLUtil.withFirstChildElement(element, "UpdateMapping", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     final UpdateMapping updateMapping = new UpdateMapping(mapping);

                     XMLUtil.forEachChildElement(element, "Case", new XMLUtil.ElementHandler()
                     {
                        private int m_nOrdinal = 0;

                        public void handleElement(Element element)
                        {
                           final UpdateMappingCase update = new UpdateMappingCase(metaclass);

                           update.setBatch(XMLUtil.getBooleanAttr(element, "batch", update.isBatch()));
                           update.setDirty(XMLUtil.getBooleanAttr(element, "dirty", update.isDirty()));
                           update.setFull(XMLUtil.getBooleanAttr(element, "full", update.isFull()));

                           Pair attributes = (Pair)m_helper.parse(
                              XMLUtil.getStringAttr(element, "attributes"),
                              true, mapping.getTextPositionMap(), null, metadata.getGlobalEnvironment()
                           );

                           update.setScript(loadScript(element, sURLPrefix + ".update." + m_nOrdinal, mapping.getTextPositionMap()));
                           updateMapping.addCase(update, attributes);
                           m_nOrdinal += 1;
                        }
                     });

                     mapping.setUpdateMapping(updateMapping);
                  }
               });

               XMLUtil.withFirstChildElement(element, "DeleteMapping", false,
                  new XMLUtil.ElementHandler()
               {
                  public void handleElement(Element element)
                  {
                     final WorkMapping operation = new WorkMapping(metaclass);

                     operation.setBatch(XMLUtil.getBooleanAttr(element, "batch", operation.isBatch()));
                     operation.setScript(loadScript(element, sURLPrefix + ".delete", mapping.getTextPositionMap()));
                     mapping.setDeleteMapping(operation);
                  }
               });

               // Key Generator
               final String sKeyGeneratorName = XMLUtil.getStringAttr(element, "keyGenerator");

               if (sKeyGeneratorName != null)
               {
                  loader.addComponentFixup(new ContextFixup(m_helper)
                  {
                     public void fixup()
                     {
                        mapping.setKeyGenerator(metadata.getComponent(sKeyGeneratorName));
                     }
                  });
               }

               mapping.setDerived(XMLUtil.getBooleanAttr(element, "derived", mapping.isDerived()));
            }
         });

         loader.addSingletonFixup(new ContextFixup(m_helper)
         {
            public void fixup()
            {
               mapping.compile(loader.getMachine());
            }
         });
      }
      finally
      {
         m_helper.restoreMarker(nCookie);
      }

      return mapping;
   }

   /**
    * Loads and parses the first <Script> tag child of element.
    * @param element The element containing the <Script> tag.
    * @param sURL The code URL. For example class:Name.persistence.create
    * @param textPosMap The parser text position map.
    * @return The parsed script.
    */
   public Pair loadScript(Element element, final String sURL, final Lookup textPosMap)
   {
      final Pair[] script = new Pair[1];

      XMLUtil.withFirstChildElement(element, "Script", true, new XMLUtil.ElementHandler()
      {
         public void handleElement(Element element)
         {
            script[0] = (Pair)m_helper.parse(
               m_helper.getElementValue(element),
               true, sURL, textPosMap, null, m_loader.getMetadata().getGlobalEnvironment());
         }
      });

      return script[0];
   }

   /**
    * @see nexj.core.meta.persistence.XMLPersistenceMetadataLoader#loadUpgrade(org.w3c.dom.Element, java.lang.String, nexj.core.meta.persistence.DataSource, nexj.core.meta.xml.XMLMetadataHelper)
    */
   public SchemaUpgrade loadUpgrade(Element element, String sName, DataSource source, XMLMetadataHelper helper)
   {
      return null;
   }
}
TOP

Related Classes of nexj.core.meta.persistence.virtual.XMLVirtualDataSourceMetadataLoader

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.