Package nexj.core.meta.xml

Source Code of nexj.core.meta.xml.XMLMetadataExporter

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

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;

import nexj.core.meta.Action;
import nexj.core.meta.Argument;
import nexj.core.meta.Aspect;
import nexj.core.meta.Attribute;
import nexj.core.meta.Component;
import nexj.core.meta.ComponentCollectionPropertyInitializer;
import nexj.core.meta.ComponentPropertyInitializer;
import nexj.core.meta.Event;
import nexj.core.meta.ExternalLibrary;
import nexj.core.meta.Metaclass;
import nexj.core.meta.Metadata;
import nexj.core.meta.MetadataException;
import nexj.core.meta.Pointcut;
import nexj.core.meta.Primitive;
import nexj.core.meta.PrimitiveCollectionPropertyInitializer;
import nexj.core.meta.PrimitivePropertyInitializer;
import nexj.core.meta.PropertyInitializer;
import nexj.core.meta.Type;
import nexj.core.meta.integration.Channel;
import nexj.core.meta.integration.CompositeMessagePart;
import nexj.core.meta.integration.CompositeMessagePartRef;
import nexj.core.meta.integration.Format;
import nexj.core.meta.integration.Message;
import nexj.core.meta.integration.MessagePart;
import nexj.core.meta.integration.PrimitiveMessagePart;
import nexj.core.meta.integration.Transformation;
import nexj.core.meta.integration.TransformationArgument;
import nexj.core.meta.integration.TransformationEndpoint;
import nexj.core.meta.integration.TransformationMapping;
import nexj.core.meta.integration.TransformationSource;
import nexj.core.meta.integration.XMLIntegrationMetadataExporter;
import nexj.core.meta.integration.XMLMessageMappingExporter;
import nexj.core.meta.integration.service.Binding;
import nexj.core.meta.integration.service.Case;
import nexj.core.meta.integration.service.Dispatch;
import nexj.core.meta.integration.service.Jump;
import nexj.core.meta.integration.service.Persist;
import nexj.core.meta.integration.service.Send;
import nexj.core.meta.integration.service.SendReceive;
import nexj.core.meta.integration.service.Service;
import nexj.core.meta.integration.service.Sync;
import nexj.core.meta.integration.service.Transform;
import nexj.core.meta.j2ee.J2EEEnvRef;
import nexj.core.meta.j2ee.J2EEProperty;
import nexj.core.meta.j2ee.J2EEResourceRef;
import nexj.core.meta.persistence.DataSource;
import nexj.core.meta.persistence.PersistenceMapping;
import nexj.core.meta.persistence.XMLPersistenceMetadataExporter;
import nexj.core.meta.workflow.Activity;
import nexj.core.meta.workflow.Branch;
import nexj.core.meta.workflow.Catch;
import nexj.core.meta.workflow.Decision;
import nexj.core.meta.workflow.FlowMacro;
import nexj.core.meta.workflow.FlowMacroScript;
import nexj.core.meta.workflow.Script;
import nexj.core.meta.workflow.Step;
import nexj.core.meta.workflow.TryCatch;
import nexj.core.meta.workflow.Variable;
import nexj.core.scripting.FormattingWriter;
import nexj.core.scripting.Intrinsic;
import nexj.core.scripting.Pair;
import nexj.core.util.J2EEUtil;
import nexj.core.util.Named;
import nexj.core.util.ObjUtil;
import nexj.core.util.PropertyUtil;
import nexj.core.util.SysUtil;
import nexj.core.util.Undefined;
import nexj.core.util.XMLWriter;

/**
* Exports metadata to an output stream.
*/
public class XMLMetadataExporter
{
   // constants

   /**
    * Export a servlet distributable element.
    */
   public final static int J2EE_DISTRIBUTABLE = 0;

   /**
    * Export a servlet confidential auth constraint.
    */
   public final static int J2EE_CONFIDENTIAL = 1;

   /**
    * Export an HTTP session timeout in minutes.
    */
   public final static int J2EE_SESSION_TIMEOUT = 2;

   /**
    * Export the HTTP context root.
    */
   public final static int J2EE_CONTEXT_ROOT = 3;

   /**
    * Export the HTTP login configuration.
    */
   public final static int J2EE_WEB_LOGIN_CONFIG = 4;

   /**
    * Export a resource-ref element.
    */
   public final static int J2EE_RESOURCE_REF = 5;

   /**
    * Export a resource-env-ref element.
    */
   public final static int J2EE_RESOURCE_ENV_REF = 6;

   /**
    * Export a message-driven element.
    */
   public final static int J2EE_MESSAGE_DRIVEN = 7;

   /**
    * Export a container-transaction element.
    */
   public final static int J2EE_CONTAINER_TRANSACTION = 8;

   /**
    * Export a test filter element.
    */
   public final static int J2EE_TEST_FILTER = 9;

   /**
    * Export a test filter mapping.
    */
   public final static int J2EE_TEST_FILTER_MAPPING = 10;

   /**
    * Export a persistence filter element.
    */
   public final static int J2EE_PERSISTENCE_FILTER = 11;

   /**
    * Export a persistence filter mapping.
    */
   public final static int J2EE_PERSISTENCE_FILTER_MAPPING = 12;

   /**
    * Export a session listener element.
    */
   public final static int J2EE_SESSION_LISTENER = 13;

   /**
    * Export portlet descriptor.
    */
   public final static int J2EE_PORTLETS = 14;

   /**
    * Export a container-specific resource-ref element.
    */
   public final static int J2EE_PLATFORM_RESOURCE_REF = 15;

   /**
    * Export a container-specific resource-env-ref element.
    */
   public final static int J2EE_PLATFORM_RESOURCE_ENV_REF = 16;

   /**
    * Export a container-specific resource ref extension element.
    */
   public final static int J2EE_PLATFORM_RESOURCE_REF_EXT = 17;

   /**
    * Export a container-specific message-driven element.
    */
   public final static int J2EE_PLATFORM_MESSAGE_DRIVEN = 18;

   /**
    * Export a container-specific MDB extension element.
    */
   public final static int J2EE_PLATFORM_MESSAGE_DRIVEN_EXT = 19;

   /**
    * Exports a container-specific activation spec element.
    */
   public final static int J2EE_PLATFORM_ACTIVATION_SPEC = 20;

   /**
    * Export a container-specific connection factory element.
    */
   public final static int J2EE_PLATFORM_CONNECTION_FACTORY = 21;

   /**
    * Export a container-specific admin object element.
    */
   public final static int J2EE_PLATFORM_ADMIN_OBJECT = 22;

   /**
    * Export a container-specific invoker-proxy-binding element.
    */
   public final static int J2EE_PLATFORM_INVOKER_PROXY_BINDING = 23;

   /**
    * Export a container-specific invoker-proxy-binding element.
    */
   public final static int J2EE_PLATFORM_REPLICATION_CONFIG = 24;

   /**
    * Export a container-specific invoker-proxy-binding element.
    */
   public final static int J2EE_PLATFORM_CLUSTER_CONFIG = 25;

   /**
    * Export a container-specific persistence interceptor element.
    */
   public final static int J2EE_PLATFORM_PERSISTENCE_INTERCEPTOR = 26;

   /**
    * Export a container-specific authentication interceptor element.
    */
   public final static int J2EE_PLATFORM_AUTH_INTERCEPTOR = 27;
  
   /**
    * Export the application classpath.
    */
   public final static int J2EE_PLATFORM_CLASSPATH = 28;

   /**
    * Export a portal-specific portlet deployment descriptor.
    */
   public final static int J2EE_PLATFORM_PORTLETS = 29;

   /**
    * Export in an J2EE application descriptor context.
    */
   public final static int J2EE_CONTEXT_APP = 0;

   /**
    * Export in an EJB descriptor context.
    */
   public final static int J2EE_CONTEXT_EJB = 1;

   /**
    * Export in a web descriptor context.
    */
   public final static int J2EE_CONTEXT_WEB = 2;

   /**
    * Export in a web descriptor context.
    */
   public final static int J2EE_CONTEXT_WEB_CERT = 3;

   /**
    * Export in a web descriptor context.
    */
   public final static int J2EE_CONTEXT_PORTLET = 4;

   /**
    * Export in a resource adapter context.
    */
   public final static int J2EE_CONTEXT_RA = 5;

   // associations

   /**
    * The output stream.
    */
   protected XMLWriter m_writer;

   // constructors

   /**
    * Creates the exporter with an XML print stream.
    * @param writer The output character stream.
    */
   public XMLMetadataExporter(XMLWriter writer)
   {
      m_writer = writer;
   }

   /**
    * Creates the exporter with an output character stream.
    * @param writer The output character stream.
    */
   public XMLMetadataExporter(Writer writer)
   {
      m_writer = new XMLWriter(writer);
   }

   // operations

   /**
    * @return The XML writer.
    */
   public XMLWriter getWriter()
   {
      return m_writer;
   }

   /**
    * @param variableItr Iterator over Variable instances.
    * @param varFilter Optional filter to test variables for inclusion.
    * @return Space-delimited string of variable names or null if iterator is empty.
    */
   private static String variableIteratorToString(Iterator variableItr, VariableFilter varFilter)
   {
      if (variableItr.hasNext())
      {
         StringBuffer tokenBuf = new StringBuffer();

         for (;;)
         {
            Variable v = (Variable)variableItr.next();

            if (varFilter == null || varFilter.accept(v))
            {
               if (tokenBuf.length() > 0)
               {
                  tokenBuf.append(" ");
               }

               tokenBuf.append(v.getName());
            }

            if (!variableItr.hasNext())
            {
               break;
            }
         }

         return (tokenBuf.length() == 0) ? null : tokenBuf.toString();
      }

      return null;
   }

   /**
    * Exports the specified transformation mapping.
    * @param mapping The mapping to export.
    * @param transformation The containing transformation.
    * @throws IOException if an error occurs.
    */
   protected void exportTransformationMapping(TransformationMapping mapping, final Transformation transformation) throws IOException
   {
      m_writer.openElement("Mapping");

      if (mapping.getName() != null)
      {
         m_writer.writeAttribute("name", mapping.getName());
      }

      exportSExpression(mapping.getCondition(), false, false, Boolean.TRUE, "condition");

      if (mapping.getDestinationCount() > 0)
      {
         m_writer.openAttribute("destination");

         for (int i = 0; i < mapping.getDestinationCount(); ++i)
         {
            if (i > 0)
            {
               m_writer.write(' ');
            }

            m_writer.writeValue(mapping.getDestination(i).getName());

            if (mapping.isFixedDestination(i))
            {
               m_writer.write('$');
            }
         }

         m_writer.closeAttribute();
      }

      m_writer.closeElement();

      if (mapping.getArgumentCount() > 0)
      {
         m_writer.startElement("Sources");

         for (int i = 0; i < mapping.getArgumentCount(); ++i)
         {
            TransformationArgument argument = mapping.getArgument(i);

            m_writer.openElement("Source");

            if (argument.getName() != null)
            {
               m_writer.writeAttribute("name", argument.getName());
            }

            if (argument.getMapping() != null)
            {
               m_writer.writeAttribute("mapping", argument.getMapping().getName());
            }
            else if (argument.getSource() != null && argument.getSource() != transformation.getRoot())
            {
               StringBuffer tokenBuf = new StringBuffer();

               for (TransformationSource source = argument.getSource();;)
               {
                  String sPrepend = source.getPart().getName();

                  if (mapping.isFixedSource(source))
                  {
                     sPrepend += "$";
                  }

                  tokenBuf.insert(0, (tokenBuf.length() == 0) ? sPrepend : sPrepend + " ");

                  source = source.getParent();

                  if (source == transformation.getRoot())
                  {
                     break;
                  }
               }

               m_writer.writeAttribute("source", tokenBuf.toString());
            }

            if (argument.isNull())
            {
               m_writer.writeAttribute("null", true);
            }

            if (argument.isDefault())
            {
               exportSExpression(argument.getDefaultValue(), false, false, Undefined.VALUE, "default");
            }

            m_writer.closeEmptyElement();
         }

         m_writer.endElement("Sources");
      }

      if (mapping.getScript() != null)
      {
         m_writer.startElement("Script");
         exportSExpression(mapping.getScript(), true, true, null, null);
         m_writer.endElement("Script");
      }

      m_writer.endElement("Mapping");
   }

   /**
    * Exports the specified transformation.
    * @param transformation The transformation to export.
    * @throws IOException if an error occurs.
    */
   public void exportTransformation(Transformation transformation) throws IOException
   {
      m_writer.openElement("Transformation");

      TransformationEndpoint source = transformation.getSource();

      if (source == null)
      {
         throw new MetadataException("err.meta.transformation.missingSource");
      }

      m_writer.openAttribute("source");

      if (source instanceof Metaclass)
      {
         m_writer.write("class:");
      }

      m_writer.write(source.getName());
      m_writer.closeAttribute();

      TransformationEndpoint destination = transformation.getDestination();

      if (destination == null)
      {
         throw new MetadataException("err.meta.transformation.missingDestination");
      }

      m_writer.openAttribute("destination");

      if (destination instanceof Metaclass)
      {
         m_writer.write("class:");
      }

      m_writer.write(destination.getName());
      m_writer.closeAttribute();
      m_writer.closeElement();

      if (transformation.getInitializer() != null)
      {
         m_writer.startElement("Initializer");
         exportSExpression(transformation.getInitializer(), true, true, null, null);
         m_writer.endElement("Initializer");
      }

      if (transformation.getMappingCount() > 0)
      {
         m_writer.startElement("Mappings");

         for (Iterator itr = transformation.getMappingIterator(); itr.hasNext();)
         {
            exportTransformationMapping((TransformationMapping)itr.next(), transformation);
         }

         m_writer.endElement("Mappings");
      }

      if (transformation.getFinalizer() != null)
      {
         m_writer.startElement("Finalizer");
         exportSExpression(transformation.getFinalizer(), true, true, null, null);
         m_writer.endElement("Finalizer");
      }

      m_writer.endElement("Transformation");
   }

   /**
    * Exports the specified service
    * @param service The service to export.
    * @throws IOException if an error occurs.
    */
   public void exportService(final Service service) throws IOException
   {
      m_writer.openElement("Service");

      String sArgList = variableIteratorToString(service.getArgumentIterator(), null);

      if (sArgList != null)
      {
         m_writer.writeAttribute("args", sArgList);
      }

      if (service.getCaption() != null)
      {
         m_writer.writeAttribute("caption", service.getCaption());
      }

      if (service.getInterface() != null)
      {
         m_writer.writeAttribute("interface", service.getInterface().getName());
      }

      if (service.getLayout() != null)
      {
         m_writer.writeAttribute("layout", service.getLayout());
      }

      if (service.isPrivileged())
      {
         m_writer.writeAttribute("privileged", service.isPrivileged());
      }

      String sVarList = variableIteratorToString(service.getVariableIterator(), new VariableFilter()
      {
         public boolean accept(Variable variable)
         {
            return variable != service.getOutput() && (variable.getFlags() & Variable.ARG) == 0;
         }
      });

      if (sVarList != null)
      {
         m_writer.writeAttribute("variables", sVarList);
      }

      if (service.getPrivilege() != null)
      {
         m_writer.writeAttribute("privilege", service.getPrivilege().getName());
      }

      m_writer.closeElement();

      exportSequence(service);

      m_writer.endElement("Service");
   }

   /**
    * Exports a message flow sequence for an activity.
    * @param activity The activity metadata object.
    * @throws IOException if an error occurs.
    */
   public void exportSequence(Activity activity) throws IOException
   {
      for (Iterator stepItr = activity.getStepIterator(); stepItr.hasNext();)
      {
         exportStep((Step)stepItr.next());
      }
   }

   /**
    * Exports the contents of a Scheme S-expression as CDATA or an escaped attribute value.
    * @param schemeExpr The expression to write.
    * @param bList True to export elements of a list.
    * @param bMultiLine True to pretty-format the output string over multiple lines when necessary.
    * @param defValue The default value used during metadata loading.
    * @param sAttrName Optional attribute name to write as an attribute key/value pair. Null to write as CDATA.
    * @throws IOException If an I/O error occurs.
    */
   public void exportSExpression(Object schemeExpr, boolean bList, boolean bMultiLine, Object defValue, String sAttrName) throws IOException
   {
      if (schemeExpr == null || ObjUtil.equal(schemeExpr, defValue))
      {
         return;
      }

      FormattingWriter writer = (bMultiLine) ? Intrinsic.createPrettyFormatter(null, true)
         : new FormattingWriter(new StringWriter(), true);

      if (bList)
      {
         if (!(schemeExpr instanceof Pair))
         {
            throw new MetadataException("err.meta.service.expectedPairObject",
               new Object[]{schemeExpr});
         }

         for (Pair list = (Pair)schemeExpr; list != null; list = list.getNext())
         {
            writer.formatUnit(list.getHead(), false);
         }
      }
      else
      {
         writer.formatUnit(schemeExpr, false);
      }

      if (sAttrName == null)
      {
         m_writer.writeCDATA(writer.getOutputString());
      }
      else
      {
         m_writer.writeAttribute(sAttrName, writer.getOutputString());
      }
   }

   /**
    * Exports the specified step.
    * @param metaclass The step to export.
    * @param exporter The branch exporter.
    * @throws IOException if an error occurs.
    */
   public void exportDecision(Decision decision, BranchExporter exporter) throws IOException
   {
      for (Iterator itr = decision.getBranchIterator(); itr.hasNext();)
      {
         Branch branch = (Branch)itr.next();

         m_writer.openElement(exporter.getElementName());

         exportSExpression(branch.getCondition(), false, false, Boolean.TRUE, "condition");

         if (branch.getCaption() != null)
         {
            m_writer.writeAttribute("caption", branch.getCaption());
         }

         if (branch.getLayout() != null)
         {
           m_writer.writeAttribute("layout", branch.getLayout());
         }

         exporter.exportActivity(branch);

         m_writer.endElement(exporter.getElementName());
      }
   }

   /**
    * Export common attributes of a step element.
    * @param step The step containing the common attributes.
    * @param sNodeName The xml node name of the step.
    * @throws IOException if an error occurs.
    */
   private void openStepElement(Step step, String sNodeName) throws IOException
   {
      m_writer.openElement(sNodeName);

      if (!(step instanceof Jump))
      {
         m_writer.writeAttribute("name", step.getName());
      }

      if (step.getNext() != null)
      {
         m_writer.writeAttribute("next", step.getNext().getName());
      }

      if (step.getLayout() != null)
      {
         m_writer.writeAttribute("layout", step.getLayout());
      }
   }

   /**
    * Exports the specified channel.
    * @param channel The channel to export.
    * @throws IOException if an error occurs.
    */
   public void exportChannel(Channel channel) throws IOException
   {
      getIntegrationMetadataExporter(channel).exportChannel(channel);
   }

   /**
    * Exports a boolean attribute value if it does not equal a default value.
    * @param sAttrName The attribute name.
    * @param bAttrValue The attribute value.
    * @param bDefValue The default value to compare against.
    * @throws IOException if an error occurs.
    */
   public void writeAttribute(String sAttrName, boolean bAttrValue, boolean bDefValue) throws IOException
   {
      if (bAttrValue != bDefValue)
      {
         m_writer.writeAttribute(sAttrName, bAttrValue);
      }
   }

   /**
    * Exports an int attribute value if it does not equal a default value.
    * @param sAttrName The attribute name.
    * @param nAttrValue The attribute value.
    * @param nDefValue The default value to compare against.
    * @throws IOException if an error occurs.
    */
   public void writeAttribute(String sAttrName, int nAttrValue, int nDefValue) throws IOException
   {
      if (nAttrValue != nDefValue)
      {
         m_writer.writeAttribute(sAttrName, nAttrValue);
      }
   }

   /**
    * Exports an long attribute value if it does not equal a default value.
    * @param sAttrName The attribute name.
    * @param lAttrValue The attribute value.
    * @param lDefValue The default value to compare against.
    * @throws IOException if an error occurs.
    */
   public void writeAttribute(String sAttrName, long lAttrValue, long lDefValue) throws IOException
   {
      if (lAttrValue != lDefValue)
      {
         m_writer.writeAttribute(sAttrName, Long.toString(lAttrValue));
      }
   }

   /**
    * Exports an string attribute value if it does not equal a default value.
    * @param sAttrName The attribute name.
    * @param sAttrValue The attribute value.
    * @param sDefValue The default value to compare against.
    * @throws IOException if an error occurs.
    */
   public void writeAttribute(String sAttrName, String sAttrValue, String sDefValue) throws IOException
   {
      if (!ObjUtil.equal(sAttrValue, sDefValue))
      {
         m_writer.writeAttribute(sAttrName, sAttrValue);
      }
   }

   /**
    * Exports common xml child (non-root) elements.
    * @param channel The source channel.
    * @throws IOException if an error occurs.
    */
   public void exportChannelElements(Channel channel) throws IOException
   {
      if (channel.getReceiver() != null)
      {
         exportComponentProperties("ReceiverProperties", channel.getReceiver(), "server");
      }

      if (channel.getBindingCount() > 0)
      {
         m_writer.startElement("ServiceBindings");

         for (int i = 0; i < channel.getBindingCount(); ++i)
         {
            Binding binding = channel.getBinding(i);

            m_writer.openElement("ServiceBinding");
            m_writer.writeAttribute("service", binding.getService().getName());

            if (binding.getOutput() != null)
            {
               m_writer.writeAttribute("output", binding.getOutput().getName());
            }

            int nArgCount = binding.getService().getArgumentCount();

            if (nArgCount > 0)
            {
               m_writer.closeElement();
               m_writer.startElement("Arguments");

               for (int nArgIndex = 0; nArgIndex < nArgCount; ++nArgIndex)
               {
                  Variable arg = binding.getService().getArgument(nArgIndex);

                  Object value = binding.getArgumentValue(arg.getName());

                  if (value != Undefined.VALUE)
                  {
                     m_writer.openElement("Argument");
                     m_writer.writeAttribute("name", arg.getName());
                     exportSExpression(value, false, false, null, "value");
                     m_writer.closeEmptyElement();
                  }
               }

               m_writer.endElement("Arguments");
               m_writer.endElement("ServiceBinding");
            }
            else
            {
               m_writer.closeEmptyElement();
            }
         }

         m_writer.endElement("ServiceBindings");
      }
   }

   /**
    * Exports common channel attributes for the root element.
    * @param channel The source channel.
    * @throws IOException if an error occurs.
    */
   public void exportChannelAttributes(Channel channel) throws IOException
   {
      if (!channel.isSendable())
      {
         m_writer.writeAttribute("send", false);
      }

      if (!channel.isReceivable())
      {
         m_writer.writeAttribute("receive", false);
      }

      switch (channel.getCombinationMode())
      {
         case Channel.COMBINE_FIRST:
            m_writer.writeAttribute("combine", "first");
            break;

         case Channel.COMBINE_ALL:
            m_writer.writeAttribute("combine", "all");
            break;
      }
   }

   /**
    * Exports the specified component.
    * @param component The component to export
    * @throws IOException if an error occurs.
    */
   public void exportComponent(Component component) throws IOException
   {
      m_writer.openElement("Component");

      switch (component.getActivation())
      {
         case Component.SINGLETON:
            m_writer.writeAttribute("activation", "singleton");
            break;

         case Component.CONTEXT:
            m_writer.writeAttribute("activation", "context");
            break;

         case Component.NEW:
            m_writer.writeAttribute("activation", "new");
            break;
      }

      m_writer.writeAttribute("type", component.getType().getName());
      m_writer.closeElement();

      exportComponentProperties("Properties", component, null);

      m_writer.endElement("Component");
   }

   /**
    * Exports the properties for the specified component.
    * @param sElementName The XML element node name.
    * @param component The component whose properties to export
    * @param sInitializerName Optional initializer name to filter for.
    * @throws IOException if an error occurs.
    */
   public void exportComponentProperties(String sElementName, Component component, String sInitializerName) throws IOException
   {
      m_writer.startElement(sElementName);

      for (Iterator itr = component.getPropertyInitializerIterator(); itr.hasNext();)
      {
         PropertyInitializer initializer = (PropertyInitializer)itr.next();

         if (sInitializerName != null && !sInitializerName.equals(initializer.getName()))
         {
            continue;
         }

         boolean bCollection = initializer.isCollection();

         if (bCollection)
         {
            m_writer.openElement("Collection");
         }
         else
         {
            m_writer.openElement("Property");
         }

         m_writer.writeAttribute("name", initializer.getName());
         m_writer.closeElement();

         if (bCollection)
         {
            Iterator valueItr = (initializer instanceof ComponentCollectionPropertyInitializer) ? ((ComponentCollectionPropertyInitializer)initializer).getComponentIterator() :
               ((PrimitiveCollectionPropertyInitializer)initializer).getValueIterator();

            while (valueItr.hasNext())
            {
               m_writer.startElement("Item");
               exportComponentProperty(valueItr.next());
               m_writer.endElement("Item");
            }

            m_writer.endElement("Collection");
         }
         else
         {
            exportComponentProperty((initializer instanceof ComponentPropertyInitializer) ? ((ComponentPropertyInitializer)initializer).getInstanceComponent() :
               ((PrimitivePropertyInitializer)initializer).getValue());
            m_writer.endElement("Property");
         }
      }

      m_writer.endElement(sElementName);
   }

   /**
    * Exports a component property value.
    * @param value The property value.
    * @throws IOException if an error occurs.
    */
   protected void exportComponentProperty(Object value) throws IOException
   {
      if (value != null)
      {
         if (value instanceof Component)
         {
            Component c = (Component)value;

            if (c.getMetadata().findComponent(c.getName()) == null)
            {
               exportComponent(c);
            }
            else
            {
               m_writer.writeValue(c.getName());
            }
         }
         else
         {
            m_writer.writeValue(value.toString());
         }
      }
   }

   /**
    * Exports the specified step.
    * @param metaclass The step to export.
    * @throws IOException if an error occurs.
    */
   public void exportStep(Step step) throws IOException
   {
      if (step instanceof FlowMacroScript)
      {
         FlowMacroScript script = (FlowMacroScript)step;
         FlowMacro macro = script.getMacro();

         openStepElement(step, macro.getName());

         for (int i = 0, n = macro.getArgumentCount(); i < n; ++i)
         {
            Object value = script.getArgumentValue(i);

            if (value == Undefined.VALUE)
            {
               continue;
            }

            FlowMacro.Argument arg = macro.getArgument(i);

            if (arg.getType() == null || arg.getType() == Primitive.ANY)
            {
               exportSExpression(value, arg.getType() == null,
                  false, arg.getDefault(), arg.getName());
            }
            else
            {
               m_writer.writeAttribute(arg.getName(), (String)Primitive.STRING.convert(value));
            }
         }

         m_writer.closeEmptyElement();
      }
      else if (step instanceof Script)
      {
         openStepElement(step, "Script");
         m_writer.closeElement();

         Script script = (Script)step;

         exportSExpression(script.getBody(), true, true, Jump.BODY, null);

         m_writer.endElement("Script");
      }
      else if (step instanceof Transform)
      {
         openStepElement(step, "Transform");

         Transform transform = (Transform)step;

         exportSExpression(transform.getTransformationExpression(), false, false, null, "transformation");

         m_writer.closeEmptyElement();
      }
      else if (step instanceof Dispatch)
      {
         openStepElement(step, "Dispatch");
         m_writer.closeElement();

         exportDecision((Dispatch)step, new BranchExporter()
         {
            public String getElementName()
            {
               return "Case";
            }

            public void exportActivity(Activity activity) throws IOException
            {
               Case c = (Case)activity;

               if (c.getMessage() != null)
               {
                  m_writer.writeAttribute("message", c.getMessage().getName());
               }

               m_writer.closeElement();

               exportSequence(activity);
            }
         });

         m_writer.endElement("Dispatch");
      }
      else if (step instanceof TryCatch)
      {
         openStepElement(step, "TryCatch");

         exportTryCatch((TryCatch)step, new ActivityExporter()
         {
            public void exportActivity(Activity activity) throws IOException
            {
               m_writer.closeElement();
               exportSequence(activity);
            }
         });

         m_writer.endElement("TryCatch");
      }
      else if (step instanceof Sync)
      {
         openStepElement(step, "Sync");

         Sync sync = (Sync)step;

         exportSExpression(sync.getSyncLink(), false, false, null, "link");
         exportOnErrorAttribute(sync.getOnError());

         m_writer.closeElement();

         exportSExpression(sync.getSyncScript(), true, true, null, null);

         m_writer.endElement("Sync");
      }
      else if (step instanceof Persist)
      {
         openStepElement(step, "Persist");

         Persist persist = (Persist)step;

         if (persist.isRespond())
         {
            m_writer.writeAttribute("respond", true);
         }

         exportOnErrorAttribute(persist.getOnError());
         m_writer.closeEmptyElement();
      }
      else if (step instanceof SendReceive)
      {
         openStepElement(step, "SendReceive");

         SendReceive send = (SendReceive)step;

         exportSExpression(send.getOutputExpression(), false, false, Boolean.TRUE, "output");

         if (send.getInterface() != null)
         {
            m_writer.writeAttribute("interface", send.getInterface().getName());
         }

         m_writer.closeEmptyElement();
      }
      else if (step instanceof Send)
      {
         openStepElement(step, "Send");

         Send send = (Send)step;

         exportSExpression(send.getOutputExpression(), false, false, null, "output");

         if (send.getInterface() != null)
         {
            m_writer.writeAttribute("interface", send.getInterface().getName());
         }

         m_writer.closeEmptyElement();
      }
      else if (step instanceof Jump)
      {
         openStepElement(step, "Goto");

         m_writer.closeEmptyElement();
      }
      else
      {
         throw new MetadataException("err.meta.service.unsupportedExportOfStepClass",
            new Object[]{step.getClass().getName()});
      }
   }

   /**
    * Exports onError attribute if nOnError is not the default value.
    * @param nOnError The onError code.
    * @throws IOException if an error occurs.
    */
   private void exportOnErrorAttribute(byte nOnError) throws IOException
   {
      switch (nOnError)
      {
         case Persist.COLLECT_ON_ERROR:
            m_writer.writeAttribute("onError", "collect");
            break;

         case Persist.COMMIT_ON_ERROR:
            m_writer.writeAttribute("onError", "commit");
            break;
      }
   }

   /**
    * Exports a flow try-catch step. Implementation is reponsible for closing containing element.
    * @param tryCatch The try catch.
    * @param exporter The activity exporter.
    * @throws IOException if an error occurs.
    */
   public void exportTryCatch(TryCatch tryCatch, final ActivityExporter exporter) throws IOException
   {
      if (tryCatch.getLayout() != null)
      {
         m_writer.writeAttribute("layout", tryCatch.getLayout());
      }

      if (tryCatch.getExceptionVariable() != null)
      {
         m_writer.writeAttribute("variable", tryCatch.getExceptionVariable().getName());
      }

      m_writer.closeElement();

      m_writer.openElement("Try");
      exporter.exportActivity(tryCatch.getTry());
      m_writer.endElement("Try");

      exportDecision(tryCatch, new BranchExporter()
      {
         public String getElementName()
         {
            return "Catch";
         }

         public void exportActivity(Activity activity) throws IOException
         {
            Catch ctch = (Catch)activity;

            if (ctch.getException() != null)
            {
               m_writer.writeAttribute("exception", ctch.getException().getName());
            }

            if (ctch.getLayout() != null)
            {
               m_writer.writeAttribute("layout", ctch.getLayout());
            }

            exporter.exportActivity(activity);
         }
      });
   }

   /**
    * Exports the specified metaclass.
    * @param metaclass The metaclass to export.
    * @throws IOException if an error occurs.
    */
   public void exportMetaclass(Metaclass metaclass) throws IOException
   {
      m_writer.openElement("Class");

      exportSExpression(metaclass.getWhere(), false, false, null, "where");
      exportSExpression(metaclass.getValidation(), false, true, Undefined.VALUE, "validation");

      if (metaclass.getAspectOverrideCount() > 0)
      {
         m_writer.openAttribute("aspects");

         for (int i = 0; i < metaclass.getAspectOverrideCount(); ++i)
         {
            if (i > 0)
            {
               m_writer.write(' ');
            }

            if (!metaclass.isAspectOverrideInclusive(i))
            {
               m_writer.write('!');
            }

            m_writer.write(metaclass.getAspectOverride(i).getName());
         }

         m_writer.closeAttribute();
      }

      if (metaclass.getBase() != null && !metaclass.getBase().getName().equals(Metadata.ROOT_CLASS_NAME))
      {
         m_writer.writeAttribute("base", metaclass.getBase().getName());
      }

      m_writer.writeAttribute("visibility", (metaclass.getVisibility() == Metaclass.PROTECTED) ? "protected" : "public");

      if (metaclass.getDescription() != null)
      {
         m_writer.writeAttribute("description", metaclass.getDescription());
      }

      m_writer.closeElement();
      m_writer.startElement("Attributes");

      for (Iterator itr = metaclass.getInstanceAttributeIterator(); itr.hasNext();)
      {
         Attribute attribute = (Attribute)itr.next();

         if (attribute.getDeclarator() == metaclass)
         {
            exportAttribute(attribute);
         }
      }

      for (Iterator itr = metaclass.getStaticAttributeIterator(); itr.hasNext();)
      {
         Attribute attribute = (Attribute)itr.next();

         if (attribute.getDeclarator() == metaclass)
         {
            exportAttribute(attribute);
         }
      }

      m_writer.endElement("Attributes");

      m_writer.startElement("Events");

      for (Iterator itr = metaclass.getEventIterator(); itr.hasNext();)
      {
         Event event = (Event)itr.next();

         if (event.getDeclarator() == metaclass)
         {
            exportEvent(event);
         }
      }

      m_writer.endElement("Events");

      if (metaclass.getPersistenceMapping() != null)
      {
         exportPersistenceMapping(metaclass.getPersistenceMapping());
      }

      m_writer.endElement("Class");
   }

   /**
    * Exports the specified attribute.
    * @param attribute The attribute to export.
    * @throws IOException if an error occurs.
    */
   public void exportAttribute(Attribute attribute) throws IOException
   {
      m_writer.openElement("Attribute");
      m_writer.writeAttribute("name", attribute.getName());
      m_writer.writeAttribute("visibility", (attribute.getVisibility() == Metaclass.PROTECTED) ? "protected" : "public");

      String sTypeName = "";
      Type type = attribute.getType();

      if (type != null)
      {
         sTypeName = type.getName();
      }

      m_writer.writeAttribute("type", sTypeName);

      if (attribute.isRequired())
      {
         m_writer.writeAttribute("required", true);
      }

      if (attribute.isCollection())
      {
         m_writer.writeAttribute("collection", true);
      }

      if (attribute.isCompatible())
      {
         m_writer.writeAttribute("compatible", true);
      }

      if (attribute.isStatic())
      {
         m_writer.writeAttribute("static", true);
      }

      if (attribute.isReadOnly())
      {
         m_writer.writeAttribute("readOnly", true);
      }

      if (attribute.getReverse() != null)
      {
         m_writer.writeAttribute("reverse", attribute.getReverse().getName());
      }

      if (attribute.getDescription() != null)
      {
         m_writer.writeAttribute("description", attribute.getDescription());
      }

      exportSExpression(attribute.getValue(), false, false, Undefined.VALUE, "value");
      exportSExpression(attribute.getInitializer(), false, true, Undefined.VALUE, "initializer");
      exportSExpression(attribute.getValidation(), false, true, Undefined.VALUE, "validation");
      exportSExpression(attribute.getWhere(), false, false, null, "where");

      switch (attribute.getCascadeMode())
      {
         case Attribute.CASCADE_CANCEL:
            m_writer.writeAttribute("cascade", "cancel");
            break;

         case Attribute.CASCADE_CLEAR:
            m_writer.writeAttribute("cascade", "clear");
            break;

         case Attribute.CASCADE_DELETE:
            m_writer.writeAttribute("cascade", "delete");
            break;
      }

      m_writer.closeEmptyElement();
   }

   /**
    * Exports the specified event.
    * @param event The event to export.
    * @throws IOException if an error occurs.
    */
   public void exportEvent(Event event) throws IOException
   {
      m_writer.openElement("Event");
      m_writer.writeAttribute("name", event.getName());

      if (event.isCompatible())
      {
         m_writer.writeAttribute("compatible", true);
      }

      m_writer.writeAttribute("visibility", (event.getVisibility() == Metaclass.PUBLIC) ? "public" : "protected");
      m_writer.writeAttribute("static", event.isStatic());

      StringBuffer buf = new StringBuffer();

      for (Iterator itr = event.getArgumentIterator(); itr.hasNext();)
      {
         buf.append(((Argument)itr.next()).getName());

         if (itr.hasNext())
         {
            buf.append(' ');
         }
      }

      if (buf.length() != 0)
      {
         m_writer.writeAttribute("args", buf.toString());
      }

      if (event.isVarArg())
      {
         m_writer.writeAttribute("vararg", true);
      }

      if (event.getPrivilege() != null)
      {
         m_writer.writeAttribute("privilege", event.getPrivilege().getName());
      }

      if (event.getAccessAttribute() != null)
      {
         m_writer.writeAttribute("access", event.getAccessAttribute().getName());
      }

      if (event.getDescription() != null)
      {
         m_writer.writeAttribute("description", event.getDescription());
      }

      m_writer.closeElement();

      if (event.getActionCount() != 0)
      {
         m_writer.startElement("Actions");

         for (Iterator itr = event.getActionIterator(); itr.hasNext();)
         {
            exportAction((Action)itr.next());
         }

         m_writer.endElement("Actions");
      }

      m_writer.endElement("Event");
   }

   /**
    * Exports the specified action.
    * @param action The action to export.
    * @throws IOException if an error occurs.
    */
   public void exportAction(Action action) throws IOException
   {
      m_writer.openElement("Action");
      m_writer.writeAttribute("name", action.getName());

      String sType = null;

      switch (action.getType())
      {
         case Action.MAIN:
            sType = "main";
            break;

         case Action.BEFORE:
            sType = "before";
            break;

         case Action.AFTER:
            sType = "after";
            break;

         case Action.AROUND:
            sType = "around";
            break;
      }

      m_writer.writeAttribute("type", sType);

      if (action.getNextAction() != null)
      {
         m_writer.writeAttribute("relative", action.getNextAction().getName());
      }

      if (action.getCondition() != null)
      {
         m_writer.writeAttribute("condition", Intrinsic.toString(action.getCondition()));
      }

      if (action.getMethod() != null)
      {
         Method method = action.getMethod();

         m_writer.writeAttribute("method", method.getClass().getName(), ".", method.getName());
      }

      m_writer.closeElement();

      exportSExpression(action.getBody(), true, true, null, null);

      m_writer.endElement("Action");
   }

   /**
    * Exports the specified persistence mapping.
    * @param mapping The mapping to export.
    * @throws IOException if an error occurs.
    */
   public void exportPersistenceMapping(PersistenceMapping mapping) throws IOException
   {
      m_writer.openElement("PersistenceMapping");
      m_writer.writeAttribute("dataSource", mapping.getDataSource().getName());

      if (mapping.getLockingAttribute() != null)
      {
         m_writer.writeAttribute("lockingAttribute", mapping.getLockingAttribute().getName());
      }

      if (mapping.getTypeCodeAttribute() != null)
      {
         m_writer.writeAttribute("classCodeAttribute", mapping.getTypeCodeAttribute().getName());
      }

      if (mapping.isTypeCodeForced())
      {
         m_writer.writeAttribute("classCodeForced", true);
      }

      if (mapping.getFragmentReplication() != PersistenceMapping.REPLICATION_NONE)
      {
         m_writer.writeAttribute("fragmentReplication",
            (mapping.getFragmentReplication() == PersistenceMapping.REPLICATION_UNICAST) ? "unicast" : "broadcast");
      }

      if (mapping.getFragmentAttribute() != null)
      {
         m_writer.writeAttribute("fragmentAttribute", mapping.getFragmentAttribute().getName());
      }

      if (mapping.getCaching() != PersistenceMapping.CACHING_NONE)
      {
         m_writer.writeAttribute("caching",
            (mapping.getCaching() == PersistenceMapping.CACHING_INSTANCE) ? "instance" : "class");
      }

      m_writer.closeElement();

      getPersistenceMetadataExporter(mapping.getDataSource()).exportMapping(mapping);
      m_writer.endElement("PersistenceMapping");
   }

   /**
    * Exports the J2EE descriptors for all the data sources in the metadata.
    * @param metadata The root metadata object.
    * @param nPart The part number, one of the J2EE_* constants.
    * @param sNamespace The part namespace infix. Cannot be null.
    * @param nContainer The container number, one of the J2EEUtil.* constants.
    * @param nContext The export context, one of the J2EE_CONTEXT_* constants.
    * @throws IOException if an error occurs.
    */
   public void exportJ2EEDescriptor(Metadata metadata, int nPart, String sNamespace, int nContainer, int nContext) throws IOException
   {
      switch (nPart)
      {
         case J2EE_DISTRIBUTABLE:
            if (metadata.isDistributed() && metadata.isReplicatedSession())
            {
               m_writer.openElement("distributable");
               m_writer.closeEmptyElement();
            }

            break;

         case J2EE_CONFIDENTIAL:
            if (metadata.isSecureTransport() || nContext == J2EE_CONTEXT_WEB_CERT)
            {
               m_writer.startElement("user-data-constraint");
               m_writer.writeElement("transport-guarantee",
                  (metadata.isSecureTransport()) ? "CONFIDENTIAL" : "INTEGRAL");
               m_writer.endElement("user-data-constraint");
            }

            break;

         case J2EE_SESSION_TIMEOUT:
            m_writer.writeInt(metadata.getSessionTimeout());
            break;

         case J2EE_CONTEXT_ROOT:
            if ("anon".equals(sNamespace))
            {
               m_writer.writeValue(metadata.getHTTPAnonymousContextRoot());
            }
            else if ("form".equals(sNamespace))
            {
               m_writer.writeValue(metadata.getHTTPFormContextRoot());
            }
            else if ("push".equals(sNamespace))
            {
               m_writer.writeValue(metadata.getHTTPPushRedirectorContextRoot());
            }
            else
            {
               m_writer.writeValue(metadata.getHTTPContextRoot());
            }

            break;

         case J2EE_WEB_LOGIN_CONFIG:
            if ("form".equals(sNamespace))
            {
               m_writer.writeElement("auth-method", "FORM");
               m_writer.startElement("form-login-config");
               m_writer.writeElement("form-login-page", metadata.getHTTPFormLoginPage());
               m_writer.writeElement("form-error-page", metadata.getHTTPFormErrorPage());
               m_writer.endElement("form-login-config");
            }
            else
            {
               m_writer.startElement("auth-method");
               m_writer.writeValue(
                  (metadata.getAuthenticationProtocol() == Metadata.AUTH_PROTOCOL_CERTIFICATE)
                  ? "CLIENT-CERT" : "BASIC"
               );
               m_writer.endElement("auth-method");

               if (metadata.getAuthenticationProtocol() != Metadata.AUTH_PROTOCOL_CERTIFICATE)
               {
                  m_writer.startElement("realm-name");

                  if (metadata.getAuthenticationDomain() != null)
                  {
                     m_writer.writeValue(metadata.getAuthenticationDomain());
                  }
                  else
                  {
                     m_writer.writeValue(SysUtil.NAMESPACE.toUpperCase(Locale.ENGLISH));
                  }

                  m_writer.endElement("realm-name");
               }
            }

            break;

         case J2EE_TEST_FILTER:
            if (metadata.isTestInterceptor())
            {
               m_writer.startElement("filter");
               m_writer.writeElement("display-name", "TestFilter");
               m_writer.writeElement("filter-name", "TestFilter");
               m_writer.writeElement("filter-class", SysUtil.PACKAGE, ".core.testing.rpc.http.TestFilter");
               m_writer.endElement("filter");
            }

            break;

         case J2EE_TEST_FILTER_MAPPING:
            if (metadata.isTestInterceptor())
            {
               m_writer.startElement("filter-mapping");
               m_writer.writeElement("filter-name", "TestFilter");
               m_writer.writeElement("url-pattern", "/*");
               m_writer.endElement("filter-mapping");
            }

            break;

         case J2EE_PERSISTENCE_FILTER:
            if (metadata.isPersistentSession())
            {
               m_writer.startElement("filter");
               m_writer.writeElement("display-name", "PersistenceFilter");
               m_writer.writeElement("filter-name", "PersistenceFilter");
               m_writer.writeElement("filter-class", SysUtil.PACKAGE, ".core.rpc.http.session.PersistenceFilter");
               m_writer.endElement("filter");
            }

            break;

         case J2EE_PERSISTENCE_FILTER_MAPPING:
            if (metadata.isPersistentSession())
            {
               m_writer.startElement("filter-mapping");
               m_writer.writeElement("filter-name", "PersistenceFilter");
               m_writer.writeElement("url-pattern", "/*");
               m_writer.endElement("filter-mapping");
            }

            break;

         case J2EE_SESSION_LISTENER:
            if (metadata.isPersistentSession())
            {
               m_writer.startElement("listener");
               m_writer.writeElement("listener-class", SysUtil.PACKAGE, ".core.rpc.http.session.SessionListener");
               m_writer.endElement("listener");
            }

            break;

         case J2EE_PORTLETS:
            exportPortlets((XMLMetadata)metadata, nContainer);
            break;

         case J2EE_PLATFORM_REPLICATION_CONFIG:
            if (metadata.isDistributed() && metadata.isReplicatedSession())
            {
               switch (nContainer)
               {
                  case J2EEUtil.JBOSS:
                     m_writer.startElement("replication-config");
                     m_writer.writeElement("replication-trigger", "SET");
                     m_writer.writeElement("replication-type", "SYNC");
                     m_writer.endElement("replication-config");

                     break;
               }
            }

            break;

         case J2EE_PLATFORM_CLUSTER_CONFIG:
            if (metadata.isDistributed())
            {
               switch (nContainer)
               {
                  case J2EEUtil.JBOSS:
                     m_writer.writeElement("clustered", "True");
                     m_writer.startElement("cluster-config");
                     m_writer.writeElement("partition-name", "${jboss.partition.name:DefaultPartition}");
                     m_writer.writeElement("home-load-balance-policy", "org.jboss.ha.framework.interfaces.FirstAvailable");
                     m_writer.writeElement("bean-load-balance-policy", "org.jboss.ha.framework.interfaces.FirstAvailable");
                     m_writer.endElement("cluster-config");

                     break;
               }
            }

            break;

         case J2EE_PLATFORM_PERSISTENCE_INTERCEPTOR:
            if (SysUtil.ENTERPRISE)
            {
               switch (nContainer)
               {
                  case J2EEUtil.JBOSS:
                     m_writer.openElement("Valve");
                     m_writer.writeAttribute("className", SysUtil.PACKAGE, ".core.container.platform.jboss.JBossPersistenceValve");
                     m_writer.writeAttribute("enabled", metadata.isPersistentSession());
                     m_writer.closeEmptyElement();

                     break;
               }
            }

            break;

         case J2EE_PLATFORM_AUTH_INTERCEPTOR:
            if (metadata.getAuthenticationProtocol() == Metadata.AUTH_PROTOCOL_SPNEGO ||
               metadata.isPersistentSession())
            {
               switch (nContainer)
               {
                  case J2EEUtil.JBOSS:
                     m_writer.openElement("Valve");
                     m_writer.writeAttribute("className", SysUtil.PACKAGE, ".core.container.platform.jboss.JBossAuthenticationValve");

                     if (metadata.getAuthenticationProtocol() == Metadata.AUTH_PROTOCOL_SPNEGO)
                     {
                        if (metadata.getAuthenticationDomain() != null)
                        {
                           m_writer.writeAttribute("domain", metadata.getAuthenticationDomain());
                        }

                        if (metadata.getAuthenticationService() != null)
                        {
                           m_writer.writeAttribute("service", metadata.getAuthenticationService());
                        }
                     }

                     m_writer.writeAttribute("sessionTimeout", metadata.getSessionTimeout());
                     m_writer.closeEmptyElement();

                     break;
               }
            }

            break;

         case J2EE_PLATFORM_PORTLETS:
            exportPortlets((XMLMetadata)metadata, nContainer);
            break;
           
         case J2EE_PLATFORM_CLASSPATH:
            for (Iterator extLibIter = metadata.getExternalLibraryIterator(); extLibIter.hasNext();)
            {
               ExternalLibrary extLib = (ExternalLibrary)extLibIter.next();

               for (Iterator fileIter = extLib.getFileIterator(); fileIter.hasNext();)
               {
                  String sFile = (String)fileIter.next();

                  switch (nContainer)
                  {
                     case J2EEUtil.WEBSPHERE:
                        m_writer.startElement("classpath");
                        m_writer.writeValue("$(APP_INSTALL_ROOT)/$(CELL)/" + SysUtil.NAMESPACE + ".ear/" + sFile);
                        m_writer.endElement("classpath");

                        break;
                  }
               }
            }

            break;
      }

      DataSource[] dataSourceArray = new DataSource[metadata.getDataSourceCount()];
      int i = 0;

      for (Iterator itr = metadata.getDataSourceIterator(); itr.hasNext(); ++i)
      {
         dataSourceArray[i] = (DataSource)itr.next();
      }

      Arrays.sort(dataSourceArray, Named.COMPARATOR);

      for (i = 0; i < dataSourceArray.length; ++i)
      {
         DataSource dataSource = dataSourceArray[i];

         if (dataSource.getType().getExporter() != null)
         {
            getPersistenceMetadataExporter(dataSource)
               .exportJ2EEDescriptor(dataSource, nPart, sNamespace, nContainer, nContext);
         }
      }

      Channel[] channelArray = new Channel[metadata.getChannelCount()];

      i = 0;

      for (Iterator itr = metadata.getChannelIterator(); itr.hasNext(); ++i)
      {
         channelArray[i] = (Channel)itr.next();
      }

      Arrays.sort(channelArray, Named.COMPARATOR);

      for (i = 0; i < channelArray.length; ++i)
      {
         Channel channel = channelArray[i];

         if (channel.getType().getExporter() != null)
         {
            getIntegrationMetadataExporter(channel)
               .exportJ2EEDescriptor(channel, nPart, sNamespace, nContainer, nContext);
         }
      }
   }
   /**
    * Exports a J2EE environment reference.
    * @param res The environment reference.
    * @param nPart The part number, one of the J2EE_* constants.
    * @param sNamespace The part namespace infix. Cannot be null.
    * @param nContainer The container number, one of the J2EEUtil.* constants.
    * @param nContext The export context, one of the J2EE_CONTEXT_* constants.
    * @throws IOException if an error occurs.
    */
   public void exportJ2EEEnvRef(J2EEEnvRef ref, int nPart, String sNamespace, int nContainer, int nContext) throws IOException
   {
      String sId = sNamespace + ((sNamespace.length() == 0) ? "" : "-") + ref.getName().replace('/', '-');

      switch (nPart)
      {
         case J2EE_RESOURCE_ENV_REF:
            m_writer.openElement("resource-env-ref");
            m_writer.writeAttribute("id", "resourceEnvRef-", sId);
            m_writer.closeElement();

            m_writer.writeElement("resource-env-ref-name", ref.getName());
            m_writer.writeElement("resource-env-ref-type", ref.getClassName());

            m_writer.endElement("resource-env-ref");

            break;

         case J2EE_PLATFORM_RESOURCE_ENV_REF:
            switch (nContainer)
            {
            case J2EEUtil.TEEE:
               m_writer.openElement("resource-env-ref");
               m_writer.writeAttribute("name", ref.getName());
               m_writer.writeAttribute("jndi-name", ref.getJNDIName());
               m_writer.closeEmptyElement();
               break;

            case J2EEUtil.JBOSS:
               m_writer.startElement("resource-env-ref");

               m_writer.writeElement("resource-env-ref-name", ref.getName());
               m_writer.writeElement("jndi-name", ref.getJNDIName());

               m_writer.endElement("resource-env-ref");

               break;

            case J2EEUtil.WEBSPHERE:
               m_writer.openElement("resourceEnvRefBindings");
               m_writer.writeAttribute("jndiName", ref.getJNDIName());
               m_writer.closeElement();

               m_writer.openElement("bindingResourceEnvRef");
               m_writer.writeAttribute("href",
                  (nContext == J2EE_CONTEXT_EJB) ? "META-INF/ejb-jar.xml" : "WEB-INF/web.xml",
                  "#resourceEnvRef-", sId);
               m_writer.closeEmptyElement();

               m_writer.endElement("resourceEnvRefBindings");

               break;
            }

            break;

         default:
            throw new IllegalArgumentException();
      }
   }

   /**
    * Exports a J2EE resource reference.
    * @param ref The resource reference to export.
    * @param nPart The part number, one of the J2EE_* constants.
    * @param sNamespace The part namespace infix. Cannot be null.
    * @param nContainer The container number, one of the J2EEUtil.* constants.
    * @param nContext The export context, one of the J2EE_CONTEXT_* constants.
    * @throws IOException if an error occurs.
    */
   public void exportJ2EEResourceRef(J2EEResourceRef ref, int nPart, String sNamespace, int nContainer, int nContext) throws IOException
   {
      String sId = sNamespace + ((sNamespace.length() == 0) ? "" : "-") + ref.getName().replace('/', '-');

      switch (nPart)
      {
         case J2EE_RESOURCE_REF:
            m_writer.openElement("resource-ref");
            m_writer.writeAttribute("id", "resourceRef-" + sId);
            m_writer.closeElement();

            m_writer.writeElement("res-ref-name", ref.getName());
            m_writer.writeElement("res-type", ref.getClassName());
            m_writer.writeElement("res-auth", (ref.getAuthAlias() == null) ? "Application" : "Container");
            m_writer.writeElement("res-sharing-scope", (ref.isShareable()) ? "Shareable" : "Unshareable");

            m_writer.endElement("resource-ref");

            break;

         case J2EE_PLATFORM_RESOURCE_REF:
            switch (nContainer)
            {
               case J2EEUtil.TEEE:
                  m_writer.openElement("resource-ref");
                  m_writer.writeAttribute("name", ref.getName());
                  m_writer.writeAttribute("jndi-name", ref.getJNDIName());
                  m_writer.closeEmptyElement();

                  break;

               case J2EEUtil.JBOSS:
                  m_writer.startElement("resource-ref");

                  m_writer.writeElement("res-ref-name", ref.getName());
                  m_writer.writeElement("jndi-name",
                     (ref.getJNDIName().indexOf(':') < 0) ? "java:/" : "", ref.getJNDIName());

                  m_writer.endElement("resource-ref");

                  break;

               case J2EEUtil.WEBSPHERE:
                  m_writer.openElement("resRefBindings");
                  m_writer.writeAttribute("jndiName", ref.getJNDIName());

                  if (ref.getAuthAlias() != null)
                  {
                     m_writer.writeAttribute("loginConfigurationName", "DefaultPrincipalMapping");
                  }

                  m_writer.closeElement();

                  m_writer.openElement("bindingResourceRef");
                  m_writer.writeAttribute("href",
                     (nContext == J2EE_CONTEXT_EJB) ? "META-INF/ejb-jar.xml" : "WEB-INF/web.xml",
                     "#resourceRef-", sId);
                  m_writer.closeEmptyElement();

                  if (ref.getAuthAlias() != null)
                  {
                     m_writer.openElement("properties");
                     m_writer.writeAttribute("name", "com.ibm.mapping.authDataAlias");
                     m_writer.writeAttribute("value", ref.getAuthAlias());
                     m_writer.closeEmptyElement();
                  }

                  m_writer.endElement("resRefBindings");

                  break;
            }

            break;

         case J2EE_PLATFORM_RESOURCE_REF_EXT:
            switch (nContainer)
            {
               case J2EEUtil.WEBSPHERE:
                  if (ref.getIsolationLevel() != Connection.TRANSACTION_NONE)
                  {
                     m_writer.openElement("resourceRefExtensions");

                     switch (ref.getIsolationLevel())
                     {
                        case Connection.TRANSACTION_READ_UNCOMMITTED:
                           m_writer.writeAttribute("isolationLevel", "TRANSACTION_READ_UNCOMMITTED");
                           break;

                        case Connection.TRANSACTION_READ_COMMITTED:
                           m_writer.writeAttribute("isolationLevel", "TRANSACTION_READ_COMMITTED");
                           break;

                        case Connection.TRANSACTION_REPEATABLE_READ:
                           m_writer.writeAttribute("isolationLevel", "TRANSACTION_REPEATABLE_READ");
                           break;

                        case Connection.TRANSACTION_SERIALIZABLE:
                           m_writer.writeAttribute("isolationLevel", "TRANSACTION_SERIALIZABLE");
                           break;
                     }

                     m_writer.closeElement();

                     m_writer.openElement("resourceRef");
                     m_writer.writeAttribute("href",
                        (nContext == J2EE_CONTEXT_EJB) ? "META-INF/ejb-jar.xml" : "WEB-INF/web.xml",
                        "#resourceRef-", sId);
                     m_writer.closeEmptyElement();

                     m_writer.endElement("resourceRefExtensions");
                  }

                  break;
            }

            break;

         case J2EE_PLATFORM_CONNECTION_FACTORY:
            switch (nContainer)
            {
               case J2EEUtil.TEEE:
                  m_writer.openElement("factory");
                  m_writer.writeAttribute("jndi-name", ref.getJNDIName());

                  /*
                   * Force same connection to get reused throughout an XA transaction
                   * for SHAREABLE resources.
                   */
                  if (ref.getTxMode() == J2EEResourceRef.TX_XA && ref.isShareable())
                  {
                     m_writer.writeAttribute("tx-associated", "true"); // same as JBoss below
                  }

                  m_writer.closeElement();

                  for (int i = 0, n = ref.getPropertyCount(); i < n; ++i)
                  {
                     J2EEProperty property = ref.getProperty(i);

                     if (property.getValue() != null)
                     {
                        m_writer.openElement("config-property");
                        m_writer.writeAttribute("name", property.getName());
                        m_writer.writeAttribute("value", property.getValue());
                        m_writer.closeEmptyElement();
                     }
                  }

                  m_writer.endElement("factory");

                  break;

               case J2EEUtil.JBOSS:
                  m_writer.startElement((ref.getTxMode() == J2EEResourceRef.TX_NONE) ?
                     "no-tx-connection-factory" : "tx-connection-factory");

                  m_writer.writeElement("jndi-name", ref.getJNDIName());

                  switch (ref.getTxMode())
                  {
                     case J2EEResourceRef.TX_LOCAL:
                        m_writer.openElement("local-transaction");
                        m_writer.closeEmptyElement();
                        break;

                     case J2EEResourceRef.TX_XA:
                        m_writer.openElement("xa-transaction");
                        m_writer.closeEmptyElement();
                        break;
                  }

                  /*
                   * Force same connection to get reused throughout an XA transaction
                   * for SHAREABLE resources.
                   */
                  if (ref.getTxMode() == J2EEResourceRef.TX_XA && ref.isShareable())
                  {
                     m_writer.openElement("track-connection-by-tx");
                     m_writer.closeEmptyElement();
                  }

                  m_writer.writeElement("rar-name", SysUtil.NAMESPACE, ".ear#", ref.getResourceAdapterName());
                  m_writer.writeElement("connection-definition", ref.getClassName());

                  for (int i = 0, n = ref.getPropertyCount(); i < n; ++i)
                  {
                     J2EEProperty property = ref.getProperty(i);

                     if (property.getValue() != null)
                     {
                        m_writer.openElement("config-property");
                        m_writer.writeAttribute("name", property.getName());
                        m_writer.writeAttribute("type", property.getTypeName());
                        m_writer.closeElement();

                        m_writer.writeValue(property.getValue());

                        m_writer.endElement("config-property");
                     }
                  }

                  if (ref.isConnectionPoolPartitioned())
                  {
                     m_writer.openElement("application-managed-security");
                     m_writer.closeEmptyElement();
                  }

                  if (ref.getAuthAlias() != null)
                  {
                     m_writer.writeElement("security-domain-and-application", ref.getAuthAlias());
                  }

                  m_writer.writeElement("max-pool-size", Integer.toString(ref.getMaxConnections()));
                  m_writer.endElement((ref.getTxMode() == J2EEResourceRef.TX_NONE) ?
                     "no-tx-connection-factory" : "tx-connection-factory");

                  break;

               case J2EEUtil.WEBSPHERE:
                  m_writer.openElement("factories");
                  m_writer.writeAttribute("xmi:type", "resources.j2c:J2CConnectionFactory");
                  m_writer.writeAttribute("name", sId);
                  m_writer.writeAttribute("jndiName", ref.getJNDIName());
                  m_writer.writeAttribute("logMissingTransactionContext", "false");
                  m_writer.writeAttribute("connectionDefinition", "connectionDefinition-", sNamespace);
                  m_writer.closeElement();

                  m_writer.startElement("propertySet");

                  for (int i = 0, n = ref.getPropertyCount(); i < n; ++i)
                  {
                     J2EEProperty property = ref.getProperty(i);

                     m_writer.openElement("resourceProperties");
                     m_writer.writeAttribute("name", property.getName());
                     m_writer.writeAttribute("type", property.getTypeName());
                     m_writer.writeAttribute("value", property.getValue());
                     m_writer.closeEmptyElement();
                  }

                  m_writer.endElement("propertySet");

                  m_writer.openElement("connectionPool");
                  m_writer.writeAttribute("minConnections", 1);
                  m_writer.writeAttribute("maxConnections", ref.getMaxConnections());
                  m_writer.closeEmptyElement();

                  m_writer.endElement("factories");

                  break;
            }

            break;

         case J2EE_PLATFORM_ADMIN_OBJECT:
            switch (nContainer)
            {
               case J2EEUtil.TEEE:
                  m_writer.openElement("admin-object");
                  m_writer.writeAttribute("jndi-name", ref.getJNDIName());
                  m_writer.writeAttribute("interface-name", ref.getClassName());
                  m_writer.closeElement();

                  for (int i = 0, n = ref.getPropertyCount(); i < n; ++i)
                  {
                     J2EEProperty property = ref.getProperty(i);

                     if (property.getValue() != null)
                     {
                        m_writer.openElement("config-property");
                        m_writer.writeAttribute("name", property.getName());
                        m_writer.writeAttribute("value", property.getValue());
                        m_writer.closeEmptyElement();
                     }
                  }

                  m_writer.endElement("admin-object");

                  break;

               case J2EEUtil.JBOSS:
                  m_writer.openElement("mbean");
                  m_writer.writeAttribute("code", "org.jboss.resource.deployment.AdminObject");
                  m_writer.writeAttribute("name", SysUtil.NAMESPACE + ".destination:name=" + ref.getJNDIName());
                  m_writer.closeElement();

                  m_writer.openElement("attribute");
                  m_writer.writeAttribute("name", "JNDIName");
                  m_writer.closeElement();
                  m_writer.writeValue(ref.getJNDIName());
                  m_writer.endElement("attribute");

                  m_writer.openElement("attribute");
                  m_writer.writeAttribute("name", "RARName");
                  m_writer.closeElement();
                  m_writer.writeValue("jboss.jca:service=RARDeployment,name='" + SysUtil.NAMESPACE + ".ear#" + ref.getResourceAdapterName() + "'");
                  m_writer.endElement("attribute");

                  m_writer.openElement("attribute");
                  m_writer.writeAttribute("name", "Type");
                  m_writer.closeElement();
                  m_writer.writeValue(ref.getClassName());
                  m_writer.endElement("attribute");

                  Properties adminObjProps = new Properties();

                  for (Iterator iter = ref.getPropertyIterator(); iter.hasNext();)
                  {
                     J2EEProperty j2eeProp = (J2EEProperty)iter.next();
                     adminObjProps.setProperty(j2eeProp.getName(), j2eeProp.getValue());
                  }

                  m_writer.openElement("attribute");
                  m_writer.writeAttribute("name", "Properties");
                  m_writer.closeElement();
                  m_writer.writeValue(PropertyUtil.toString(adminObjProps));
                  m_writer.endElement("attribute");

                  m_writer.endElement("mbean");

                  break;

               case J2EEUtil.WEBSPHERE:
                  m_writer.openElement("j2cAdminObjects");
                  m_writer.writeAttribute("name", sId);
                  m_writer.writeAttribute("jndiName", ref.getJNDIName());
                  m_writer.writeAttribute("adminObject", "adminObject-", sNamespace);
                  m_writer.closeElement();

                  for (Iterator iter = ref.getPropertyIterator(); iter.hasNext();)
                  {
                     J2EEProperty j2eeProp = (J2EEProperty)iter.next();

                     m_writer.openElement("properties");
                     m_writer.writeAttribute("name", j2eeProp.getName());
                     m_writer.writeAttribute("type", j2eeProp.getTypeName());
                     m_writer.writeAttribute("value", j2eeProp.getValue());
                     m_writer.closeEmptyElement();
                  }

                  m_writer.endElement("j2cAdminObjects");

                  break;
            }

            break;

         default:
            throw new IllegalArgumentException();
      }
   }
   /**
    * Exports a J2EE activation property.
    * @param property The activation property to export.
    * @param nContainer The container number, one of the J2EEUtil.* constants.
    * @param nContext The export context, one of the J2EE_CONTEXT_* constants.
    * @throws IOException if an error occurs.
    */
   public void exportJ2EEActivationProperty(J2EEProperty property, int nContainer, int nContext) throws IOException
   {
      if (property != null && property.getValue() != null)
      {
         if (nContext == J2EE_CONTEXT_APP)
         {
            switch (nContainer)
            {
               case J2EEUtil.WEBSPHERE:
                  m_writer.openElement("resourceProperties");
                  m_writer.writeAttribute("name", property.getName());
                  m_writer.writeAttribute("type", property.getTypeName());
                  m_writer.writeAttribute("value", property.getValue());
                  m_writer.closeEmptyElement();

                  break;
            }
         }
         else
         {
            m_writer.startElement("activation-config-property");
            m_writer.writeElement("activation-config-property-name", property.getName());
            m_writer.writeElement("activation-config-property-value", property.getValue());
            m_writer.endElement("activation-config-property");
         }
      }
   }

   /**
    * Gets a persistence metadata exporter for a given data source.
    * @param dataSource The data source.
    * @return The exporter.
    * @throws IOException if an error occurs.
    */
   protected XMLPersistenceMetadataExporter getPersistenceMetadataExporter(DataSource dataSource) throws IOException
   {
      try
      {
         return (XMLPersistenceMetadataExporter)dataSource.getType().getExporter()
            .getConstructor(new Class[]{XMLMetadataExporter.class})
            .newInstance(new Object[]{this});
      }
      catch (Exception e)
      {
         throw new IOException("Cannot instantiate the persistence metadata exporter \"" +
            dataSource.getType().getExporter().getName() + "\"");
      }
   }

   /**
    * Gets an integration metadata exporter for a given data source.
    * @param dataSource The data source.
    * @return The exporter.
    * @throws IOException if an error occurs.
    */
   protected XMLIntegrationMetadataExporter getIntegrationMetadataExporter(Channel channel) throws IOException
   {
      try
      {
         return (XMLIntegrationMetadataExporter)channel.getType().getExporter()
            .getConstructor(new Class[]{XMLMetadataExporter.class})
            .newInstance(new Object[]{this});
      }
      catch (Exception e)
      {
         throw new IOException("Cannot instantiate the integration metadata exporter \"" +
            channel.getType().getExporter().getName() + "\"");
      }
   }

   /**
    * Gets a message mapping exporter for a given format.
    * @param format The format.
    * @return The exporter.
    * @throws IOException if an error occurs.
    */
   protected XMLMessageMappingExporter getMessageMappingExporter(Format format) throws IOException
   {
      try
      {
         return (XMLMessageMappingExporter)format.getExporter()
            .getConstructor(new Class[]{XMLMetadataExporter.class})
            .newInstance(new Object[]{this});
      }
      catch (Exception e)
      {
         throw new IOException("Cannot instantiate the message mapping exporter \"" +
            format.getExporter().getName() + "\"");
      }
   }

   /**
    * Exports the specified message.
    * @param mapping The message to export.
    * @throws IOException if an error occurs.
    */
   public void exportMessage(Message message) throws IOException
   {
      XMLMessageMappingExporter mappingExporter = null;

      if (message.getFormat() != null)
      {
         mappingExporter = getMessageMappingExporter(message.getFormat());
      }

      exportCompositeMessagePart(message, message.getRoot(), mappingExporter);
   }

   /**
    * Exports a composite message.
    * @param rootMsg The root message associated with the message, if any.
    * @param message The message.
    * @param export The message mapping exporter.
    * @throws IOException if an error occurs.
    */
   protected void exportCompositeMessagePart(Message rootMsg, CompositeMessagePart message, XMLMessageMappingExporter exporter) throws IOException
   {
      m_writer.openElement("Message");

      if (rootMsg != null)
      {
         if (rootMsg.getFormat() != null)
         {
            m_writer.writeAttribute("format", rootMsg.getFormat().getName());
         }

         if (rootMsg.getResponse() != null)
         {
            m_writer.writeAttribute("response", rootMsg.getResponse().getName());
         }

         if (rootMsg.getBaseMessage() != null)
         {
            m_writer.writeAttribute("base", rootMsg.getBaseMessage().getName());
         }

         if (message.getDescription() != null)
         {
            m_writer.writeAttribute("description", message.getDescription());
         }
      }
      else
      {
         exportMessagePartAttributes(message);
      }

      if (message instanceof CompositeMessagePartRef)
      {
         m_writer.writeAttribute("ref",
            ((CompositeMessagePartRef)message).getRefPart().getName());

         if (rootMsg != null)
         {
            m_writer.closeEmptyElement();
         }
         else
         {
            m_writer.closeElement();
            exportMessagePartMapping(rootMsg, message, exporter);
            m_writer.endElement("Message");
         }
      }
      else
      {
         String sAggregation;

         switch (message.getAggregation())
         {
            case CompositeMessagePart.RANDOM:
               sAggregation = "random";
               break;

            case CompositeMessagePart.SINGLE:
               sAggregation = "single";
               break;

            default:
               sAggregation = "sequential";
               break;
         }

         m_writer.writeAttribute("aggregation", sAggregation);

         if (message.isLax())
         {
            m_writer.writeAttribute("lax", true);
         }

         m_writer.closeElement();
         exportMessagePartMapping(rootMsg, message, exporter);

         if (message.getPartCount() > 0)
         {
            m_writer.startElement("Parts");

            for (Iterator iter = message.getPartIterator(); iter.hasNext();)
            {
               MessagePart part = (MessagePart)iter.next();

               if (part instanceof CompositeMessagePart)
               {
                  exportCompositeMessagePart(null, (CompositeMessagePart)part, exporter);
               }
               else if (part instanceof PrimitiveMessagePart)
               {
                  exportPrimitiveMessagePart((PrimitiveMessagePart)part, exporter);
               }
            }

            m_writer.endElement("Parts");
         }

         m_writer.endElement("Message");
      }
   }

   /**
    * Exports a primitive message.
    * @param message The message.
    * @param export The message mapping exporter.
    * @throws IOException if an error occurs.
    */
   protected void exportPrimitiveMessagePart(PrimitiveMessagePart message, XMLMessageMappingExporter exporter) throws IOException
   {
      m_writer.openElement("Value");

      if (message.getType() != null)
      {
         m_writer.writeAttribute("type", message.getType().getName());
      }

      exportMessagePartAttributes(message);

      m_writer.closeElement();

      exportMessagePartMapping(null, message, exporter);

      if (message.getEnumerationCount() > 0)
      {
         m_writer.startElement("Enumerations");

         for (Iterator iter = message.getEnumerationIterator(); iter.hasNext();)
         {
            m_writer.openElement("Enumeration");

            Object enumValue = iter.next();
            m_writer.writeAttribute("value", Primitive.toString(enumValue));
            m_writer.closeEmptyElement();
         }

         m_writer.endElement("Enumerations");
      }

      m_writer.endElement("Value");
   }

   /**
    * Exports the message mapping using an exporter
    * @param rootMsg The root message associated with message if any
    * @param message The message with a mapping.
    * @param exporter The exporter.
    * @throws IOException if an error occurs.
    */
   protected void exportMessagePartMapping(Message rootMsg, MessagePart message, XMLMessageMappingExporter exporter) throws IOException
   {
      if (exporter != null)
      {
         exporter.exportMapping(rootMsg, message.getMapping());
      }
   }

   /**
    * Exports common attributes from a message part.
    * @param message The message part.
    * @throws IOException if an error occurs
    */
   protected void exportMessagePartAttributes(MessagePart messagePart) throws IOException
   {
      m_writer.writeAttribute("name", messagePart.getName());
      m_writer.writeAttribute("minCount", Integer.toString(messagePart.getMinCount()));
      m_writer.writeAttribute("maxCount", Integer.toString(
         (messagePart.getMaxCount() == Integer.MAX_VALUE) ? 0 : messagePart.getMaxCount()));

      if (messagePart.getDescription() != null)
      {
         m_writer.writeAttribute("description", messagePart.getDescription());
      }
   }

   /**
    * Gets the aspect override expression as a string.
    * @param pointcut The pointcut containing the aspect overrides.
    * @return The aspect override expression.
    */
   public static String getAspectOverrides(Pointcut pointcut)
   {
      StringBuffer buf = new StringBuffer();

      for (int i = 0, n = pointcut.getAspectOverrideCount(); i < n; ++i)
      {
         if (i != 0)
         {
            buf.append(' ');
         }

         if (!pointcut.isAspectOverrideInclusive(i))
         {
            buf.append('!');
         }

         buf.append(pointcut.getAspectOverride(i).getName());
      }

      return (buf.length() == 0) ? null : buf.toString();
   }

   /**
    * Gets the pointcut expression as a string.
    * @param aspect The aspect specifying the pointcuts.
    * @return The pointcut expression.
    */
   public static String getPointcuts(Aspect aspect)
   {
      StringBuffer buf = new StringBuffer();

      for (int i = 0, n = aspect.getPointcutPatternCount(); i < n; ++i)
      {
         if (i != 0)
         {
            buf.append(' ');
         }

         if (!aspect.isPointcutPatternInclusive(i))
         {
            buf.append('!');
         }

         buf.append(aspect.getPointcutPattern(i));
      }

      return (buf.length() == 0) ? null : buf.toString();
   }

   /**
    * Iterates UI metadata and exports portlet descriptor.
    * @param metadata XMLMetadata object.
    * @param nContainer The container, one of the J2EEUtil.* constants.
    * @throws IOException if an error occurs.
    */
   protected void exportPortlets(XMLMetadata metadata, int nContainer) throws IOException
   { // Portlets not supported
   }

   /**
    * Interface implemented by activity exporter strategies.
    */
   public interface ActivityExporter
   {
      /**
       * Exports an activity. The container element has been opened but not closed. Method is responsible for closing element.
       * @param activity The activity to export.
       * @throws IOException if an error occurs.
       */
      void exportActivity(Activity activity) throws IOException;
   }

   /**
    * Interface implemented by flow decision exporter strategies.
    */
   public interface BranchExporter extends ActivityExporter
   {
      /**
       * @return The branch element name.
       * @throws IOException if an error occurs.
       */
      String getElementName() throws IOException;
   }

   /**
    * Interface for filtering variables.
    */
   public interface VariableFilter
   {
      /**
       * @param variable The variable to be tested.
       * @return true to include the variable.
       */
      boolean accept(Variable variable);
   }
}
TOP

Related Classes of nexj.core.meta.xml.XMLMetadataExporter

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.