Storage.java :  » UML » MetaBoss » com » metaboss » sdlctools » domains » enterprisemodel » storage » xmlfileimpl » Java Open Source

Java Open Source » UML » MetaBoss 
MetaBoss » com » metaboss » sdlctools » domains » enterprisemodel » storage » xmlfileimpl » Storage.java
// THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
// OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright 2000-2005  Softaris Pty.Ltd. All Rights Reserved.
package com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationException;
import javax.xml.bind.Validator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.metaboss.enterprise.ps.PSContentConstraintViolationException;
import com.metaboss.enterprise.ps.PSDataSourceOperationInvocationException;
import com.metaboss.enterprise.ps.PSException;
import com.metaboss.enterprise.ps.PSIllegalArgumentException;
import com.metaboss.enterprise.ps.PSReadDataIntegrityViolationException;
import com.metaboss.enterprise.ps.PSUndefinedSystemPropertyException;
import com.metaboss.enterprise.ps.PSUnexpectedProgramConditionException;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.ApplicationDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.AssociationDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.DataTypeDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.DomainDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.EnterpriseDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.EntityDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.MessageDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.ReportDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.ServiceDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.ServicemoduleDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.StructureDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.SystemDefType;
import com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom.TypeTemplateDefType;
import com.metaboss.sdlctools.types.enterprisemodel.TemplateSourceType;
import com.metaboss.util.DirectoryUtils;
import com.metaboss.util.StringUtils;

/** This class is an interface between ps layer and dom storage */
public class Storage
{
  private static final Log sLogger = LogFactory.getLog(Storage.class);
  
    // Will make it into settable thing in the future
    private static final String cRootDir = System.getProperty("MetaBoss.SystemDefinitionPath", "C:\\MetaBoss\\SampleSystemDefinition");
    private static final String cEnterpriseRootDir = cRootDir + File.separator + "Enterprises";
    private static final String cEnterpriseSystemsSubDir = "Systems";
    private static final String cEnterpriseDatatypesSubDir = "Types";
    private static final String cEnterpriseDomainsSubDir = "Domains";
    private static final String cEnterpriseServicemodulesSubDir = "Services";
    private static final String cEnterpriseServicemodulesServicesSubDir = "service";
    private static final String cEnterpriseServicemodulesDatastructuresSubDir = "datastructure";
    private static final String cEnterpriseApplicationsSubDir = File.separator + "Applications";
    private static final String cDatatypesSubDir = "datatype";
    private static final String cTypetemplatesSubDir = "typetemplate";
    
  // Subdirectory of the metalib where all typetemplates can be found
  private static final String sTypeTemplateMetaLibSubDir = File.separator + "EnterpriseModel" + File.separator + "typetemplate";
  // Subdirectory of the metalib where all datatypes can be found
  private static final String sDataTypeMetaLibSubDir = File.separator + "EnterpriseModel" + File.separator + "datatype";
    
    private static JAXBContext cJAXBContext = null;
    private static Unmarshaller cUnmarshaller = null;
  private static Marshaller cMarshaller = null;
  private static Validator cValidator = null;
    
  // Helper. Provides single point of access to JAXBContext
  private static JAXBContext getJAXBContext() throws JAXBException
  {
    if (cJAXBContext == null)
    {
      // create a JAXBContext capable of handling classes generated into the primer.po package
      cJAXBContext = JAXBContext.newInstance( "com.metaboss.sdlctools.domains.enterprisemodel.storage.xmlfileimpl.dom" );
    }
    return cJAXBContext;
  }  

    // Helper. Provides single point of access to Unmarshaller
  private static Unmarshaller getUnmarshaller() throws JAXBException
  {
    if (cUnmarshaller == null)
    {
      // create an Unmarshaller
      cUnmarshaller = getJAXBContext().createUnmarshaller();
    }
    return cUnmarshaller;
  }  
  
  // Helper. Provides single point of access to Marshaller
  private static Marshaller getMarshaller() throws JAXBException
  {
    if (cMarshaller == null)
    {
      // create an Marshaller
      cMarshaller = getJAXBContext().createMarshaller();
      cMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
    }
    return cMarshaller;
  }  

  // Helper. Provides single point of access to Validator
  private static Validator getValidator() throws JAXBException
  {
    if (cValidator == null)
    {
      // create an Marshaller
      cValidator = getJAXBContext().createValidator();
    }
    return cValidator;
  }  

    private static HashMap cDOMObjectsCache = new HashMap();
    /** Returns enterprise def or null if none found */
    public static EnterpriseDefType getEnterprise(String pEnterpriseRef) throws PSException
    {
        // First see if we have this object already
        EnterpriseDefType lRet = (EnterpriseDefType)cDOMObjectsCache.get(pEnterpriseRef + ";" + EnterpriseDefType.class.getName());
        if (lRet == null)
        {
            // EnterpriseRef always consists of single part - enterprise name
            StringTokenizer lTokenizer = new StringTokenizer(pEnterpriseRef,".",false);
            if (lTokenizer.countTokens() != 1)
                throw new PSException("Invalid EnterpriseRef: " + pEnterpriseRef);
            String lEnterpriseName = lTokenizer.nextToken();
            // Enterprise definition is located right under enterprises
            String lEnterpriseFileName = cEnterpriseRootDir + File.separator +
                                         pEnterpriseRef + File.separator +
                                         "Descriptor.xml";
            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lEnterpriseFileName);
                if (lInputStream != null)
                {
                    if((lRet = (EnterpriseDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getEnterpriseRef().equals(pEnterpriseRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between EnterpriseRef stored in file and the one implied by its location. EnterpriseRef : " + lRet.getEnterpriseRef() + ", Location : " + lEnterpriseFileName);
                        cDOMObjectsCache.put(pEnterpriseRef + ";" + EnterpriseDefType.class.getName(),lRet);
                    }
                }
            }
      catch(JAXBException e)
      {
        throw new PSDataSourceOperationInvocationException(e);
      }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** All services found in the module */
    public static String[] getServicemoduleServiceRefs(String pServicemoduleRef) throws PSException
    {
        ServicemoduleDefType lServicemoduleDef = getServicemodule(pServicemoduleRef);
        if (lServicemoduleDef == null)
           throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleRef);
        ArrayList lServiceRefs = new ArrayList();
        List lServices = lServicemoduleDef.getServiceDefList().getServiceDef();
        Iterator lIter = lServices.iterator();
        while (lIter.hasNext())
        {
            ServiceDefType lServiceDef = (ServiceDefType)lIter.next();
            lServiceRefs.add(lServiceDef.getServiceRef());
        }
        return  (String[])lServiceRefs.toArray(new String[lServiceRefs.size()]);
    }

    /** All structures found in the module */
    public static String[] getServicemoduleStructureRefs(String pServicemoduleRef) throws PSException
    {
        ServicemoduleDefType lServicemoduleDef = getServicemodule(pServicemoduleRef);
        if (lServicemoduleDef == null)
           throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleRef);
        ArrayList lStructureRefs = new ArrayList();
        List lStructures = lServicemoduleDef.getStructureDefList().getStructureDef();
        Iterator lIter = lStructures.iterator();
        while (lIter.hasNext())
        {
            StructureDefType lStructureDef = (StructureDefType)lIter.next();
            lStructureRefs.add(lStructureDef.getStructureRef());
        }
        return  (String[])lStructureRefs.toArray(new String[lStructureRefs.size()]);
    }

    /** All messages found in the module */
    public static String[] getServicemoduleMessageRefs(String pServicemoduleRef) throws PSException
    {
        ServicemoduleDefType lServicemoduleDef = getServicemodule(pServicemoduleRef);
        if (lServicemoduleDef == null)
           throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleRef);
        ArrayList lMessageRefs = new ArrayList();
        List lMessages = lServicemoduleDef.getMessageDefList().getMessageDef();
        Iterator lIter = lMessages.iterator();
        while (lIter.hasNext())
        {
            MessageDefType lMessageDef = (MessageDefType)lIter.next();
            lMessageRefs.add(lMessageDef.getMessageRef());
        }
        return  (String[])lMessageRefs.toArray(new String[lMessageRefs.size()]);
    }

    /** All entities found in the domain */
    public static String[] getDomainEntityRefs(String pDomainRef) throws PSException
    {
        DomainDefType lDomainDef = getDomain(pDomainRef);
        if (lDomainDef == null)
            throw new com.metaboss.enterprise.ps.PSIllegalArgumentException("Unknown domain. DomainRef: " + pDomainRef);
        // Iterate through associations - building matching datatype references
        List lEntities = lDomainDef.getEntityDefList().getEntityDef();
        String[] lReturnEntityRefs = new String[lEntities.size()];
        Iterator lIter = lEntities.iterator();
        for (int i = 0; lIter.hasNext(); i++)
        {
            EntityDefType lEntityDef = (EntityDefType)lIter.next();
            lReturnEntityRefs[i] = lEntityDef.getEntityRef();
        }
        return lReturnEntityRefs;
    }

    /** All enterprises found in the installation */
    public static String[] getEnterpriseRefs() throws PSException
    {
        // Loop through directory and report enterprise names
        String lEnterprisesDirName = cEnterpriseRootDir;

        File lEnterprisesDir = new File(lEnterprisesDirName);
        if (!lEnterprisesDir.exists())
            return new String[0]; // No entities

        File[] lEnterpriseDirs = lEnterprisesDir.listFiles();
        if (lEnterpriseDirs == null)
            return new String[0]; // No entities

        // Iterate through directories - building matching enterprise references
        String[] lReturnEnterpriseRefs = new String[lEnterpriseDirs.length];
        for (int i = 0; i < lEnterpriseDirs.length; i++)
            lReturnEnterpriseRefs[i] = lEnterpriseDirs[i].getName();
        return lReturnEnterpriseRefs;
    }


    /** All datatypes  found in the domain */
    public static String[] getSystemDatatypeRefs(String pSystemRef) throws PSException
    {
        try
        {
            String lDatatypeDirRootName = getSystemDirectory(pSystemRef) + File.separator +
                                          cEnterpriseDatatypesSubDir;
            File lEnterpriseDatatypeDir = new File(lDatatypeDirRootName);
            if (!lEnterpriseDatatypeDir.exists())
            {
                // There are not types directory - may be there are no types ?
                if (lEnterpriseDatatypeDir.getParentFile().exists())
                    return new String[0]; // No types, but there is a system. This is as good as no types defined
                throw new PSIllegalArgumentException("System not found. SystemRef: " + pSystemRef);
            }
            String[] lAllDatatypeDirectories = DirectoryUtils.listAllDirectoriesWithName(lDatatypeDirRootName, "datatype");
            // Iterate through directories - building matching datatype references
            ArrayList lAllRefs = new ArrayList();
            for (int i = 0; i < lAllDatatypeDirectories.length; i++)
            {
                String lDatatypeDirName = lAllDatatypeDirectories[i];
                String lDatatypeDirMiddleName = lDatatypeDirName.substring(lDatatypeDirRootName.length() + 1, lDatatypeDirName.length() - 9);
                String lBeginningOfRef = pSystemRef + ".";
                if (!lDatatypeDirMiddleName.equals("-"))
                    lBeginningOfRef += StringUtils.replace(lDatatypeDirMiddleName, File.separator, ".") + ".";

                File lDatatypeDir = new File(lDatatypeDirName);
                File[] lDatatypeDirs = lDatatypeDir.listFiles();
                if (lDatatypeDirs != null && lDatatypeDirs.length > 0)
                {
                    // Iterate through this datatype directory and build matching datatype references
                    for (int j = 0; j < lDatatypeDirs.length; j++)
                    {
                        lAllRefs.add(lBeginningOfRef + lDatatypeDirs[j].getName());
                    }
                }
            }
            return (String[])lAllRefs.toArray(new String[lAllRefs.size()]);
        }
        catch(java.io.FileNotFoundException e)
        {
            throw new PSException("Caught exception while scanning for System Datatypes. SystemRef: " + pSystemRef, e);
        }

    }

    /** All typetemplates  found in the domain */
    public static String[] getSystemTypetemplateRefs(String pSystemRef) throws PSException
    {
        try
        {
            String lDatatypeDirRootName = getSystemDirectory(pSystemRef) + File.separator +
                                          cEnterpriseDatatypesSubDir;
            File lEnterpriseDatatypeDir = new File(lDatatypeDirRootName);
            if (!lEnterpriseDatatypeDir.exists())
            {
                // There are not types directory - may be there are no types ?
                if (lEnterpriseDatatypeDir.getParentFile().exists())
                    return new String[0]; // No types, but there is a system. This is as good as no types defined
                throw new PSIllegalArgumentException("System not found. SystemRef: " + pSystemRef);
            }
            String[] lAllTypetemplateDirectories = DirectoryUtils.listAllDirectoriesWithName(lDatatypeDirRootName, "typetemplate");
            // Iterate through directories - building matching datatype references
            ArrayList lAllRefs = new ArrayList();
            for (int i = 0; i < lAllTypetemplateDirectories.length; i++)
            {
                String lTypetemplateDirName = lAllTypetemplateDirectories[i];
                String lTypetemplateDirMiddleName = lTypetemplateDirName.substring(lDatatypeDirRootName.length() + 1, lTypetemplateDirName.length() - 13);
                String lBeginningOfRef = pSystemRef + ".";
                if (!lTypetemplateDirMiddleName.equals("-"))
                    lBeginningOfRef += StringUtils.replace(lTypetemplateDirMiddleName, File.separator, ".") + ".";

                File lTypetemplateDir = new File(lTypetemplateDirName);
                File[] lTypetemplateDirs = lTypetemplateDir.listFiles();
                if (lTypetemplateDirs != null && lTypetemplateDirs.length > 0)
                {
                    // Iterate through this datatype directory and build matching datatype references
                    for (int j = 0; j < lTypetemplateDirs.length; j++)
                    {
                        lAllRefs.add(lBeginningOfRef + lTypetemplateDirs[j].getName());
                    }
                }
            }
            return (String[])lAllRefs.toArray(new String[lAllRefs.size()]);
        }
        catch(java.io.FileNotFoundException e)
        {
            throw new PSException("Caught exception while scanning for System Typetemplates. SystemRef: " + pSystemRef, e);
        }

    }

    /** All systems found in this enterprise */
    public static String[] getEnterpriseSystemRefs(String pEnterpriseRef) throws PSException
    {
        try
        {
            // EnterpriseRef always consists of single part - enterprise name
            StringTokenizer lTokenizer = new StringTokenizer(pEnterpriseRef,".",false);
            if (lTokenizer.countTokens() != 1)
                throw new PSException("Invalid EnterpriseRef: " + pEnterpriseRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemsRootDirName = cEnterpriseRootDir + File.separator +
                                         lEnterpriseName + File.separator +
                                         cEnterpriseSystemsSubDir;
            File lSystemsRootDir = new File(lSystemsRootDirName);
            if (!lSystemsRootDir.exists())
            {
                // There are no systems directory - may be there are no systems ?
                if (lSystemsRootDir.getParentFile().exists())
                    return new String[0]; // No systems, but there is an enterprise. This is as good as no systems defined
                throw new PSIllegalArgumentException("Enterprise not found. EnterpriseRef : " + pEnterpriseRef);
            }
            String[] lAllSystemsDirectories = DirectoryUtils.listAllChildDirectoriesInDirectory(lSystemsRootDir.getAbsolutePath());
            // Iterate through directories - building matching system references
            ArrayList lAllRefs = new ArrayList();
            for (int i = 0; i < lAllSystemsDirectories.length; i++)
            {
                String lSystemDirName = lAllSystemsDirectories[i];
                int lLastDir = lSystemDirName.lastIndexOf(File.separator);
                String lSystemName = lSystemDirName.substring(lLastDir + 1);
                lAllRefs.add(lEnterpriseName + "." + lSystemName);
            }
            return (String[])lAllRefs.toArray(new String[lAllRefs.size()]);
        }
        catch(java.io.FileNotFoundException e)
        {
            throw new PSException("Caught exception while scanning for System references. EnterpriseRef: " + pEnterpriseRef, e);
        }

    }

    /** All datatypes  found in the domain */
    public static String[] getSystemServicemoduleRefs(String pSystemRef) throws PSException
    {
        String lSystemDirectoryName = getSystemDirectory(pSystemRef);
        if (new File(lSystemDirectoryName).exists() == false)
            throw new PSException("Directory " + lSystemDirectoryName + " does not exist. Unable to read system definition. SystemRef:" + pSystemRef);
        String lSystemName =  pSystemRef.substring(pSystemRef.lastIndexOf(".")+1);
        String lServicemoduleDirRootName = lSystemDirectoryName + File.separator +
                                           cEnterpriseServicemodulesSubDir;
        File lServicemoduleDir = new File(lServicemoduleDirRootName);
        if ( (!lServicemoduleDir.isDirectory()) || (!lServicemoduleDir.exists()))
            return new String[0];
        // Iterate through directories - building matching datatype references
        ArrayList lAllRefs = new ArrayList();
        File[] lServicemoduleDirs = lServicemoduleDir.listFiles();
        if (lServicemoduleDirs != null && lServicemoduleDirs.length > 0)
        {
            // Iterate through this datatype directory and build matching datatype references
            for (int j = 0; j < lServicemoduleDirs.length; j++)
            {
                File lFile = lServicemoduleDirs[j];
                if (lFile.isDirectory())
                    lAllRefs.add(pSystemRef + "." + lServicemoduleDirs[j].getName());
            }
        }
        return (String[])lAllRefs.toArray(new String[lAllRefs.size()]);
    }

    /** All associations found in the domain */
    public static String[] getDomainReportRefs(String pDomainRef) throws PSException
    {
        DomainDefType lDomainDef = getDomain(pDomainRef);
        if (lDomainDef == null)
            throw new PSIllegalArgumentException("Unknown domain. DomainRef : " + pDomainRef);
        // Iterate through associations - building matching datatype references
        List lReports = lDomainDef.getReportDefList().getReportDef();
        String[] lReturnReportRefs = new String[lReports.size()];
        Iterator lIter = lReports.iterator();
        for (int i = 0; lIter.hasNext(); i++)
        {
            ReportDefType lReportDef = (ReportDefType)lIter.next();
            lReturnReportRefs[i] = lReportDef.getReportRef();
        }
        return lReturnReportRefs;
    }

    /** All associations found in the domain */
    public static String[] getDomainAssociationRefs(String pDomainRef) throws PSException
    {
        DomainDefType lDomainDef = getDomain(pDomainRef);
        if (lDomainDef == null)
            throw new PSIllegalArgumentException("Unknown domain. DomainRef: " + pDomainRef);
        // Iterate through associations - building matching datatype references
        List lAssociations = lDomainDef.getAssociationDefList().getAssociationDef();
        String[] lReturnAssociationRefs = new String[lAssociations.size()];
        Iterator lIter = lAssociations.iterator();
        for (int i = 0; lIter.hasNext(); i++)
        {
            AssociationDefType lAssociationDef = (AssociationDefType)lIter.next();
            lReturnAssociationRefs[i] = lAssociationDef.getAssociationRef();
        }
        return lReturnAssociationRefs;
    }

    /** Returns domain def or null if none found */
    public static DomainDefType getDomain(String pDomainRef) throws PSException
    {
        // First see if we have this object already
        DomainDefType lRet = (DomainDefType)cDOMObjectsCache.get(pDomainRef + ";" + DomainDefType.class.getName());
        if (lRet == null)
        {
            // DomainRef always consists of three parts - enterprise name . system name . domain name
            StringTokenizer lTokenizer = new StringTokenizer(pDomainRef,".",false);
            if (lTokenizer.countTokens() != 3)
                throw new PSException("Invalid DomainRef: " + pDomainRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lDomainName = lTokenizer.nextToken();
            String lDomainFileName = cEnterpriseRootDir + File.separator +
                                     lEnterpriseName + File.separator +
                                     cEnterpriseSystemsSubDir + File.separator +
                                     lSystemName + File.separator +
                                     cEnterpriseDomainsSubDir + File.separator +
                                     lDomainName + "DomainDescriptor.xml";

            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lDomainFileName);
                if (lInputStream != null)
                {
                    if((lRet = (DomainDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getDomainRef().equals(pDomainRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between DomainRef stored in file and the one implied by its location. DomainRef : " + lRet.getDomainRef() + ", Location : " + lDomainFileName);
                        cDOMObjectsCache.put(pDomainRef + ";" + DomainDefType.class.getName(),lRet);
                    }
                }
            }
            catch(JAXBException e)
            {
                throw new PSDataSourceOperationInvocationException(e);
            }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** Returns system def or null if none found */
    public static SystemDefType getSystem(String pSystemRef) throws PSException
    {
        // First see if we have this object already
        SystemDefType lRet = (SystemDefType)cDOMObjectsCache.get(pSystemRef + ";" + SystemDefType.class.getName());
        if (lRet == null)
        {
            String lSystemDirectoryName = getSystemDirectory(pSystemRef);
            if (new File(lSystemDirectoryName).exists() == false)
                throw new PSException("Directory " + lSystemDirectoryName + " does not exist. Unable to read system definition. SystemRef:" + pSystemRef);
            String lSystemFileName = lSystemDirectoryName + File.separator + "Descriptor.xml";
            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lSystemFileName);
                if (lInputStream != null)
                {
                    if((lRet = (SystemDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getSystemRef().equals(pSystemRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between SystemRef stored in file and the one implied by its location. SystemRef: " + lRet.getSystemRef() + ", Location: " + lSystemFileName);
                        cDOMObjectsCache.put(pSystemRef + ";" + SystemDefType.class.getName(),lRet);
                    }
                }
            }
            catch(JAXBException e)
            {
                throw new PSDataSourceOperationInvocationException(e);
            }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** Returns DataType def or null if none found */
    public static DataTypeDefType getDatatype(String pDataTypeRef) throws PSException
    {
        // First see if we have this object already
        DataTypeDefType lRet = (DataTypeDefType)cDOMObjectsCache.get(pDataTypeRef + ";" + DataTypeDefType.class.getName());
        if (lRet == null)
        {
            String lDatatypeDirectoryName = getDataTypeDirectory(pDataTypeRef);
            if (lDatatypeDirectoryName == null)
                throw new PSException("DataType directory not found. Unable to resolve data type. DataTypeRef=" + pDataTypeRef);
            String lDataTypeFileName = lDatatypeDirectoryName + File.separator + "Descriptor.xml";
            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lDataTypeFileName);
                if (lInputStream != null)
                {
                    if((lRet = (DataTypeDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getDataTypeRef().equals(pDataTypeRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between DatatypeRef stored in file and the one implied by its location. DatatypeRef : " + lRet.getDataTypeRef() + ", Location : " + lDataTypeFileName);
                        cDOMObjectsCache.put(pDataTypeRef + ";" + DataTypeDefType.class.getName(),lRet);
                    }
                }
            }
            catch(JAXBException e)
            {
                throw new PSDataSourceOperationInvocationException("Exception caught during processing of Data Type. DataTypeRef : " + pDataTypeRef, e);
            }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** Returns DataType def or null if none found */
    public static void deleteDatatype(String pDataTypeRef) throws PSException
    {
      if (pDataTypeRef.startsWith("."))
      throw new PSIllegalArgumentException("Attempt to delete public Datatype. DatatypeRef : " + pDataTypeRef);
        String lDatatypeDirectoryName = getDataTypeDirectory(pDataTypeRef);
        if (lDatatypeDirectoryName == null)
           throw new PSException("Attempt to delete nonexistent Datatype. DatatypeRef : " + pDataTypeRef);
        String lDatatypeFileName = lDatatypeDirectoryName + File.separator + "Descriptor.xml";
        cDOMObjectsCache.remove(lDatatypeFileName + ";" + DataTypeDefType.class.getName());
    }

    /** Deletes Servicemodule */
    public static void deleteServicemodule(String pServicemoduleRef) throws PSException
    {
        // ServciemoduleRef always consists of three parts - enterprise name . system name . serviemodule name
        StringTokenizer lTokenizer = new StringTokenizer(pServicemoduleRef,".",false);
        if (lTokenizer.countTokens() != 3)
            throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleRef);
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lServicemoduleFileName = cEnterpriseRootDir + File.separator +
                                     lEnterpriseName + File.separator +
                                     cEnterpriseSystemsSubDir + File.separator +
                                     lSystemName + File.separator +
                                     cEnterpriseServicemodulesSubDir + File.separator +
                                     lServicemoduleName + "ServicemoduleDescriptor.xml";
        File lServicemoduleFile = new File(lServicemoduleFileName);
        if (lServicemoduleFile.exists() == false)
            throw new PSException("File " + lServicemoduleFileName + " does not exist. Unable to delete servicemodule. ServicemoduleRef: " + pServicemoduleRef);
        if (lServicemoduleFile.canWrite() == false)
            throw new PSException("File " + lServicemoduleFileName + " is read-only. Unable to delete servicemodule. ServicemoduleRef: " + pServicemoduleRef);
        if (!lServicemoduleFile.delete())
            throw new PSException("Unable to delete servicemodule. ServicemoduleRef: " + pServicemoduleRef);
        cDOMObjectsCache.remove(pServicemoduleRef + ";" + ServicemoduleDefType.class.getName());
    }

  /** Deletes Enterprise */
  public static void deleteEnterprise(String pEnterpriseRef) throws PSException
  {
    try
    {
      String lEnterpriseDirectoryName = getEnterpriseDirectory(pEnterpriseRef);
      File lEnterpriseDirectory = new File(lEnterpriseDirectoryName);
      if (!lEnterpriseDirectory.exists())
        throw new PSException("Directory " + lEnterpriseDirectoryName + " does not exist. Unable to delete enterprise. EnterpriseRef: " + pEnterpriseRef);
      if (!DirectoryUtils.canDelete(lEnterpriseDirectory))
        throw new PSException("Directory " + lEnterpriseDirectoryName + " is not writeable. Unable to delete enterprise. EnterpriseRef: " + pEnterpriseRef);
      cDOMObjectsCache.remove(pEnterpriseRef + ";" + EnterpriseDefType.class.getName());
      DirectoryUtils.deleteDirectory(lEnterpriseDirectory);
    }
    catch(IOException e)
    {
      throw new PSException("Caught exception while deleting Enterprise. EnterpriseRef: " + pEnterpriseRef, e);
    }
  }

    /** Returns DataType def or null if none found */
    public static void insertDatatype(DataTypeDefType pDataTypeDef) throws PSException
    {
      try
      {
          try
          {
        getValidator().validate(pDataTypeDef);
          }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Datatype definition validation exception. DatatypeRef: " + pDataTypeDef.getDataTypeRef(), e);
      }
      if (pDataTypeDef.getDataTypeRef().startsWith("."))
        throw new PSIllegalArgumentException("Attempt to insert public Datatype. DatatypeRef : " + pDataTypeDef.getDataTypeRef());
          String lDatatypeDirectoryName = getDataTypeDirectory(pDataTypeDef.getDataTypeRef());
          if (lDatatypeDirectoryName != null)
             throw new PSException("Attempt to insert alredy existing Datatype. DatatypeRef : " + pDataTypeDef.getDataTypeRef());
      lDatatypeDirectoryName = suggestEnterpriseDataTypeDirectory(pDataTypeDef.getDataTypeRef());   
          String lDatatypeFileName = lDatatypeDirectoryName + File.separator + "Descriptor.xml";
          FileOutputStream lFileOutputStream = null;
          try
          {
        DirectoryUtils.ensureNewCleanDirectory(lDatatypeDirectoryName);
              lFileOutputStream = new FileOutputStream(lDatatypeFileName,false);
        getMarshaller().marshal(pDataTypeDef,lFileOutputStream);
              lFileOutputStream.flush();
              lFileOutputStream.close();
              lFileOutputStream = null;
              cDOMObjectsCache.put(pDataTypeDef.getDataTypeRef() + ";" + DataTypeDefType.class.getName(),pDataTypeDef);
          }
          catch(IOException e)
          {
              throw new PSException("Caught exception while writing file : " + lDatatypeFileName, e);
          }
          finally
          {
              try
              {
                  if (lFileOutputStream != null)
                      lFileOutputStream.close();
              }
              catch(IOException e)
              {
              }
          }
      }          
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    }

    /** Returns DataType def or null if none found */
    public static void updateDatatype(DataTypeDefType pDataTypeDef) throws PSException
    {
      try
      {
      try
      {
        getValidator().validate(pDataTypeDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Datatype definition validation exception. DatatypeRef: " + pDataTypeDef.getDataTypeRef(), e);
      }
      if (pDataTypeDef.getDataTypeRef().startsWith("."))
        throw new PSIllegalArgumentException("Attempt to update public Datatype. DatatypeRef : " + pDataTypeDef.getDataTypeRef());
          String lDatatypeDirectoryName = getDataTypeDirectory(pDataTypeDef.getDataTypeRef());
          if (lDatatypeDirectoryName == null)
              throw new PSException("Datatype directory not found. Unable to resolve data type. DataTypeRef: " + pDataTypeDef.getDataTypeRef());
          String lDataTypeFileName = lDatatypeDirectoryName + File.separator + "Descriptor.xml";
          File lDataTypeFile = new File(lDataTypeFileName);
          if (lDataTypeFile.exists() == false || lDataTypeFile.isFile() == false)
             throw new PSException("Attempt to update Datatype, which does not exists. DataTypeRef : " + pDataTypeDef.getDataTypeRef());
          if (!lDataTypeFile.canWrite())
             throw new PSException("Datatype file is read-only. DataTypeRef : " + pDataTypeDef.getDataTypeRef());
          // Clean up the cache prior to saving the new file
          cDOMObjectsCache.remove(pDataTypeDef.getDataTypeRef() + ";" + DataTypeDefType.class.getName());
          FileOutputStream lFileOutputStream = null;
          try
          {
              lFileOutputStream = new FileOutputStream(lDataTypeFileName,false);
        getMarshaller().marshal(pDataTypeDef,lFileOutputStream);
              lFileOutputStream.flush();
              lFileOutputStream.close();
              lFileOutputStream = null;
              cDOMObjectsCache.put(pDataTypeDef.getDataTypeRef() + ";" + DataTypeDefType.class.getName(),pDataTypeDef);
          }
          catch(IOException e)
          {
              throw new PSException("Caught exception while writing file : " + lDataTypeFileName, e);
          }
          finally
          {
              try
              {
                  if (lFileOutputStream != null)
                      lFileOutputStream.close();
              }
              catch(IOException e)
              {
              }
          }
      }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    }


    /** Returns DataType source or null if none found */
    public static String getDatatypeSource(String pDataTypeRef,String pFileSuffix) throws PSException
    {
        String lDatatypeDirectoryName = getDataTypeDirectory(pDataTypeRef);
        if (lDatatypeDirectoryName == null)
            throw new PSException("DataType directory not found. Unable to resolve data type. DataTypeRef: " + pDataTypeRef);
        int lLastDotIndex = pDataTypeRef.lastIndexOf(".");
        String lDataTypeSourceFileName = lDatatypeDirectoryName + File.separator + pDataTypeRef.substring(lLastDotIndex+1) + pFileSuffix + ".java";

        // Load this file
        InputStream lInputStream = null;
        try
        {
            lInputStream = openFileStream(lDataTypeSourceFileName);
            if (lInputStream != null)
            {
                return StringUtils.readTextStreamFully(lInputStream);
            }
            return null;
        }
        catch(IOException e)
        {
            throw new PSException("Caught exception while reading file : " + lDataTypeSourceFileName, e);
        }
        finally
        {
            try
            {
                if (lInputStream != null)
                    lInputStream.close();
            }
            catch(IOException e)
            {
            }
        }
    }

    /** Returns Service implementation source */
    public static com.metaboss.sdlctools.types.enterprisemodel.ZipArchive getServiceImplementationSource(String pServiceRef, String pSourceName) throws PSException
    {
        try
        {
            String lServiceDirectoryName = getServiceDirectory(pServiceRef);
            File lDirectoryFile = new File(lServiceDirectoryName);
            if (lDirectoryFile.exists() == false || lDirectoryFile.isDirectory() == false)
                throw new PSException("Directory " + lServiceDirectoryName + " does not exist. Unable to resolve service. ServiceRef=" + pServiceRef);
            String lSourceArchiveFileName = lServiceDirectoryName + File.separator + pSourceName + ".zip";
            File lSourceArchiveFile = new File(lServiceDirectoryName + File.separator + pSourceName + ".zip");
            if (lSourceArchiveFile.exists() == false || lSourceArchiveFile.isFile() == false || lSourceArchiveFile.canRead() == false)
                throw new PSException("Source archive " + lSourceArchiveFileName + " does not exist. Unable to resolve service the implementation source . ServiceRef : " + pServiceRef + " SourceName : " + pSourceName);
            return com.metaboss.sdlctools.types.enterprisemodel.ZipArchive.createFromFile(pSourceName, lSourceArchiveFile);
        }
        catch(com.metaboss.enterprise.datatypes.DataTypeException e)
        {
            throw new com.metaboss.enterprise.ps.PSDatatypeOperationException(e);
        }
    }

    /** Returns Service implementation source */
    public static void updateServiceImplementationSource(String pServiceRef, com.metaboss.sdlctools.types.enterprisemodel.ZipArchive pSourceArchive) throws PSException
    {
        if (pSourceArchive.isConcealed())
            return; // Stop unathorised updates
        if (pSourceArchive.isEmpty())
            throw new PSException("Unable to update source from an empty archive. ServiceRef=" + pServiceRef);
        String lServiceDirectoryName = getServiceDirectory(pServiceRef);
        File lDirectoryFile = new File(lServiceDirectoryName);
        if (lDirectoryFile.exists() == false || lDirectoryFile.isDirectory() == false)
            throw new PSException("Directory " + lServiceDirectoryName + " does not exist. Unable to resolve service. ServiceRef=" + pServiceRef);
        String lSourceArchiveFileName = lServiceDirectoryName + File.separator + pSourceArchive.getName() + ".zip";
        // Save this file
        FileOutputStream lFileOutputStream = null;
        try
        {
            lFileOutputStream = new FileOutputStream(lSourceArchiveFileName);
            lFileOutputStream.write(pSourceArchive.getData());
            lFileOutputStream.flush();
        }
        catch(IOException e)
        {
            throw new PSException("Caught exception while writing file : " + lSourceArchiveFileName, e);
        }
        finally
        {
            try
            {
                if (lFileOutputStream != null)
                    lFileOutputStream.close();
            }
            catch(IOException e)
            {
            }
        }
    }

    /** Returns DataType def or null if none found */
    public static TypeTemplateDefType getTypeTemplate(String pTypeTemplateRef) throws PSException
    {
        // First see if we have this object already
        TypeTemplateDefType lRet = (TypeTemplateDefType)cDOMObjectsCache.get(pTypeTemplateRef + ";" + TypeTemplateDefType.class.getName());
        if (lRet == null)
        {
            String lTypeTemplateDirectory = getTypeTemplateDirectory(pTypeTemplateRef);
            if (lTypeTemplateDirectory == null)
              throw new PSException("TypeTemplate directory not found. Unable to read TypeTemplate definition. TypeTemplateRef: " + pTypeTemplateRef);
            String lTypeTemplateFileName = lTypeTemplateDirectory + File.separator + "Descriptor.xml";
            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lTypeTemplateFileName);
                if (lInputStream != null)
                {
                    if((lRet = (TypeTemplateDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getTypeTemplateRef().equals(pTypeTemplateRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between TypeTemplateRef stored in file and the one implied by its location. TypeTemplateRef : " + lRet.getTypeTemplateRef() + ", Location : " + lTypeTemplateFileName);
                        cDOMObjectsCache.put(pTypeTemplateRef + ";" + TypeTemplateDefType.class.getName(),lRet);
                    }
                }
            }
            catch(JAXBException e)
            {
                throw new PSDataSourceOperationInvocationException("Exception caught during reading of Type Template. TypeTemplateRef : " + pTypeTemplateRef, e);
            }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** Returns TypeTemplate source or null if none found */
    public static String getTypeTemplateSource(String pTypeTemplateRef) throws PSException
    {
        TypeTemplateDefType lDef = getTypeTemplate(pTypeTemplateRef);
        String lTypeTemplateName = pTypeTemplateRef.substring(pTypeTemplateRef.lastIndexOf(".")+1);
        // Work on file extension
        String lFileExtension = null;
        TemplateSourceType lSourceType = TemplateSourceType.createFromString(lDef.getTypeTemplateSourceType());
        if (lSourceType.equals(TemplateSourceType.VELOCITY))
            lFileExtension = "vtl";
        else
        if (lSourceType.equals(TemplateSourceType.JAVA))
            lFileExtension = "java";
        else
            throw new PSException("SourceType element is empty or has invalid value. Unable to read TypeTemplate source file. TypeTemplate Ref : " + pTypeTemplateRef);
        String lTypeTemplateDirectory = getTypeTemplateDirectory(pTypeTemplateRef);    
    if (lTypeTemplateDirectory == null)
      throw new PSException("TypeTemplate directory not found. Unable to read TypeTemplate source. TypeTemplateRef: " + pTypeTemplateRef);
        String lTypeTemplateSourceFileName = lTypeTemplateDirectory + File.separator + lTypeTemplateName + "." + lFileExtension;
        // Load this file
        InputStream lInputStream = null;
        try
        {
            lInputStream = openFileStream(lTypeTemplateSourceFileName);
            if (lInputStream != null)
            {
                return StringUtils.readTextStreamFully(lInputStream);
            }
            throw new PSException("Unable to find or read TypeTemplate source file. TypeTemplate Ref : " + pTypeTemplateRef + "  Expected file : " + lTypeTemplateSourceFileName);
        }
        catch(IOException e)
        {
            throw new PSException("Caught exception while reading file : " + lTypeTemplateSourceFileName, e);
        }
        finally
        {
            try
            {
                if (lInputStream != null)
                    lInputStream.close();
            }
            catch(IOException e)
            {
            }
        }
    }

    /** Stores given tytpe template source in its place */
    public static void updateTypeTemplateSource(String pTypeTemplateRef, String pTypeTemplateSource) throws PSException
    {
    if (pTypeTemplateRef.startsWith("."))
      throw new PSIllegalArgumentException("Attempt to update public TypeTemplate. TypeTemplateRef : " + pTypeTemplateRef);
        TypeTemplateDefType lDef = getTypeTemplate(pTypeTemplateRef);
        String lTypeTemplateName = pTypeTemplateRef.substring(pTypeTemplateRef.lastIndexOf("."));
        // Work on file extension
        String lFileExtension = null;
        TemplateSourceType lSourceType = TemplateSourceType.createFromString(lDef.getTypeTemplateSourceType());
        if (lSourceType.equals(TemplateSourceType.VELOCITY))
            lFileExtension = "vtl";
        else
        if (lSourceType.equals(TemplateSourceType.JAVA))
            lFileExtension = "java";
        else
            throw new PSException("SourceType element is empty or has invalid value. Unable to read TypeTemplate source file. TypeTemplate Ref : " + pTypeTemplateRef);
    String lTypeTemplateDirectory = getTypeTemplateDirectory(pTypeTemplateRef);    
    if (lTypeTemplateDirectory == null)
      throw new PSException("TypeTemplate directory not found. Unable to update TypeTemplate source. TypeTemplateRef: " + pTypeTemplateRef);
        String lTypeTemplateSourceFileName = lTypeTemplateDirectory + File.separator + lTypeTemplateName + "." + lFileExtension;
        // Save this file
        FileWriter lWriter = null;
        try
        {
            lWriter = new FileWriter(lTypeTemplateSourceFileName,false);
            lWriter.write(pTypeTemplateSource);
        }
        catch(IOException e)
        {
            throw new PSException(e);
        }
        finally
        {
            if (lWriter != null)
            {
                try
                {
                    lWriter.flush();
                }
                catch(IOException e)
                {
                    // Ignore
                }
                try
                {
                    lWriter.close();
                }
                catch(IOException e)
                {
                    // Ignore
                }
            }
        }
    }

    /** Returns all references to type templates stored in libraries */
    public static String[] getPublicTypeTemplateRefs() throws PSException
    {
        try
        {
      HashSet lRefs = new HashSet();
      String[] lMetaLibPath = getPublicMetaModelPath();
      for (int i = 0; i < lMetaLibPath.length; i++)
      {
        String lTypetemplatesLibDir = lMetaLibPath[i] + sTypeTemplateMetaLibSubDir;
        // Directory may not exist - just skip
        if (new File(lTypetemplatesLibDir).exists() == false)
          continue; // No typetemplates here
        String [] lAllTypeTemplateDirs = DirectoryUtils.listAllDescendantDirectoriesInDirectory(lTypetemplatesLibDir);
        int lPrefixLength = lTypetemplatesLibDir.length();
        for (int j = 0; j < lAllTypeTemplateDirs.length; j++)
        {
          String lTypetemplateDir = lAllTypeTemplateDirs[j];
          // We will only consider directory if it has Descriptor.xml in it
          File lDescriptorFile = new File(lTypetemplateDir + File.separator + "Descriptor.xml");
          if (lDescriptorFile.exists() && lDescriptorFile.isFile())
          {
            // Cut out root dir prefix from the beginning and replace file separators with dots
            // Note that File.separator will remain in front after cutting out the root dir
            // therefore leading dot will appear after replacement
            String lTypetemplateRef = StringUtils.replace(lTypetemplateDir.substring(lPrefixLength), File.separator, ".");
            // Add to the refs
            lRefs.add(lTypetemplateRef);
          }
        }
      }
            return (String[])lRefs.toArray(new String[lRefs.size()]);
        }
        catch(java.io.FileNotFoundException e)
        {
            throw new PSException("Caught exception while scanning for Public Typetemplate references.", e);
        }
    }

    /** Returns all references to universal type templates */
    public static String[] getPublicDatatypeRefs() throws PSException
    {
    try
    {
      HashSet lRefs = new HashSet();
      String[] lMetaLibPath = getPublicMetaModelPath();
      for (int i = 0; i < lMetaLibPath.length; i++)
      {
        String lDatatypesLibDir = lMetaLibPath[i] + sDataTypeMetaLibSubDir;
        // Directory may not exist - just skip
        if (new File(lDatatypesLibDir).exists() == false)
          continue; // No typetemplates here
        String [] lAllDataTypeDirs = DirectoryUtils.listAllDescendantDirectoriesInDirectory(lDatatypesLibDir);
        int lPrefixLength = lDatatypesLibDir.length();
        for (int j = 0; j < lAllDataTypeDirs.length; j++)
        {
          String lDataTypeDir = lAllDataTypeDirs[j];
          // We will only consider directory if it has Descriptor.xml in it
          File lDescriptorFile = new File(lDataTypeDir + File.separator + "Descriptor.xml");
          if (lDescriptorFile.exists() && lDescriptorFile.isFile())
          {
            // Cut out root dir prefix from the beginning and replace file separators with dots
            // Note that File.separator will remain in front after cutting out the root dir
            // therefore leading dot will appear after replacement
            String lDataTypeRef = StringUtils.replace(lDataTypeDir.substring(lPrefixLength), File.separator, ".");
            // Add to the refs
            lRefs.add(lDataTypeRef);
          }
        }
      }
      return (String[])lRefs.toArray(new String[lRefs.size()]);
    }
    catch(java.io.FileNotFoundException e)
    {
      throw new PSException("Caught exception while scanning for Public DataType references.", e);
    }
    }

    // Helper. Returns fully qualified directory where data type details can be found
    private static String getDataTypeDirectory(String pDataTypeRef) throws PSException
    {
        // Data Type may be in public use packages (ref must begin with dot in this case)
        // Otherwise DataTypeRef consists of three or more parts - enterprise name . system name [. sub package name] . datatype name
        if (pDataTypeRef.startsWith("."))
        {
            // Public datatype, convert its name back to the directory name
            // and try on a path until we will get it
            String lDataTypeSubdirectoryName = StringUtils.replace(pDataTypeRef,".", File.separator);
      String[] lMetaLibPath = getPublicMetaModelPath();
      for (int i = 0; i < lMetaLibPath.length; i++)
      {
        String lProspectiveDirectoryPath = lMetaLibPath[i] + sDataTypeMetaLibSubDir + lDataTypeSubdirectoryName;
        File lProspectiveDirectory = new File(lProspectiveDirectoryPath);
        if (lProspectiveDirectory.exists() && lProspectiveDirectory.isDirectory())
          return lProspectiveDirectoryPath; // Found first hit
      }
      return null;
        }
        // Enterprise datatype below this point
    String lProspectiveDirectoryPath = suggestEnterpriseDataTypeDirectory(pDataTypeRef);
    File lProspectiveDirectory = new File(lProspectiveDirectoryPath);
    if (lProspectiveDirectory.exists() && lProspectiveDirectory.isDirectory())
      return lProspectiveDirectoryPath; // Found first hit
    return null;
    }

  // Helper. Returns prospective fully qualified directory where data type details can be found
  // only works for enterprise datatypes
  private static String suggestEnterpriseDataTypeDirectory(String pDataTypeRef) throws PSException
  {
    // Data Type may be in public use packages (ref must begin with dot in this case)
    // Otherwise DataTypeRef consists of three or more parts - enterprise name . system name [. sub package name] . datatype name
    if (pDataTypeRef.startsWith("."))
      throw new PSIllegalArgumentException("Unable to suggest directory name for the public datatype. DataTypeRef: " + pDataTypeRef);
    // Enterprise datatype below this point
    StringBuffer lDataTypeDirectoryName = new StringBuffer();
    StringTokenizer lTokenizer = new StringTokenizer(pDataTypeRef,".",false);
    int lTokenCount = lTokenizer.countTokens();
    if (lTokenCount < 3)
      throw new PSIllegalArgumentException("Invalid DataTypeRef: " + pDataTypeRef);
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    lDataTypeDirectoryName.append(cEnterpriseRootDir);
    lDataTypeDirectoryName.append(File.separator);
    lDataTypeDirectoryName.append(lEnterpriseName);
    lDataTypeDirectoryName.append(File.separator);
    lDataTypeDirectoryName.append(cEnterpriseSystemsSubDir);
    lDataTypeDirectoryName.append(File.separator);
    lDataTypeDirectoryName.append(lSystemName);
    lDataTypeDirectoryName.append(File.separator);
    lDataTypeDirectoryName.append(cEnterpriseDatatypesSubDir);
    // Append posible subdirectories
    if (lTokenCount == 3)
    {
      lDataTypeDirectoryName.append(File.separator);
      lDataTypeDirectoryName.append("-");
    }
    else
    {
      for (int i = 2; i < lTokenCount - 1; i++)
      {
        lDataTypeDirectoryName.append(File.separator);
        lDataTypeDirectoryName.append(lTokenizer.nextToken());
      }
    }
    lDataTypeDirectoryName.append(File.separator);
    lDataTypeDirectoryName.append(cDatatypesSubDir);
    lDataTypeDirectoryName.append(File.separator);
    lDataTypeDirectoryName.append(lTokenizer.nextToken());
    return lDataTypeDirectoryName.toString();
  }

    // Helper. Returns fully qualified directory where system details can be found
    private static String getSystemDirectory(String pSystemRef) throws PSException
    {
        // SystemRef always consists of two parts - enterprise name . system name
        StringTokenizer lTokenizer = new StringTokenizer(pSystemRef,".",false);
        if (lTokenizer.countTokens() != 2)
            throw new PSException("Invalid SystemRef: " + pSystemRef);
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();

        // Build the name
        StringBuffer lSystemDirectoryName = new StringBuffer();
        lSystemDirectoryName.append(cEnterpriseRootDir);
        lSystemDirectoryName.append(File.separator);
        lSystemDirectoryName.append(lEnterpriseName);
        lSystemDirectoryName.append(File.separator);
        lSystemDirectoryName.append(cEnterpriseSystemsSubDir);
        lSystemDirectoryName.append(File.separator);
        lSystemDirectoryName.append(lSystemName);
        return lSystemDirectoryName.toString();
    }

  // Helper. Returns fully qualified directory where enterprise details can be found
  private static String getEnterpriseDirectory(String pEnterpriseRef) throws PSException
  {
    // SystemRef always consists of two parts - enterprise name . system name
    StringTokenizer lTokenizer = new StringTokenizer(pEnterpriseRef,".",false);
    if (lTokenizer.countTokens() != 1)
      throw new PSIllegalArgumentException("Invalid EnterpriseRef: " + pEnterpriseRef);
    String lEnterpriseName = lTokenizer.nextToken();
    // Build the name
    StringBuffer lEnterpriseDirectoryName = new StringBuffer();
    lEnterpriseDirectoryName.append(cEnterpriseRootDir);
    lEnterpriseDirectoryName.append(File.separator);
    lEnterpriseDirectoryName.append(lEnterpriseName);
    return lEnterpriseDirectoryName.toString();
  }

    // Helper. Returns fully qualified directory where service details can be found
    private static String getServiceDirectory(String pServiceRef) throws PSException
    {
        // Service ref consists of four parts - enterprise name . system name . servicemodule name . service name
        StringTokenizer lTokenizer = new StringTokenizer(pServiceRef,".",false);
        int lTokenCount = lTokenizer.countTokens();
        if (lTokenCount != 4)
            throw new PSException("Invalid ServiceRef : " + pServiceRef);
        // Build the name
        StringBuffer lServiceDirectoryName = new StringBuffer();
        lServiceDirectoryName.append(cEnterpriseRootDir);
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(lTokenizer.nextToken()); // Enterprise
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(cEnterpriseSystemsSubDir);
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(lTokenizer.nextToken()); // System
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(cEnterpriseServicemodulesSubDir);
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(lTokenizer.nextToken()); // Servicemodule
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(cEnterpriseServicemodulesServicesSubDir);
        lServiceDirectoryName.append(File.separator);
        lServiceDirectoryName.append(lTokenizer.nextToken()); // Service name
        return lServiceDirectoryName.toString();
    }

    // Helper. Returns fully qualified directory where service details can be found
    private static String getServicemoduleDirectory(String pServicemoduleRef) throws PSException
    {
        // Servicemodule ref consists of three  parts - enterprise name . system name . servicemodule name
        StringTokenizer lTokenizer = new StringTokenizer(pServicemoduleRef,".",false);
        int lTokenCount = lTokenizer.countTokens();
        if (lTokenCount != 3)
            throw new PSException("Invalid ServicemoduleRef : " + pServicemoduleRef);
        // Build the name
        StringBuffer lServicemoduleDirectoryName = new StringBuffer();
        lServicemoduleDirectoryName.append(cEnterpriseRootDir);
        lServicemoduleDirectoryName.append(File.separator);
        lServicemoduleDirectoryName.append(lTokenizer.nextToken()); // Enterprise
        lServicemoduleDirectoryName.append(File.separator);
        lServicemoduleDirectoryName.append(cEnterpriseSystemsSubDir);
        lServicemoduleDirectoryName.append(File.separator);
        lServicemoduleDirectoryName.append(lTokenizer.nextToken()); // System
        lServicemoduleDirectoryName.append(File.separator);
        lServicemoduleDirectoryName.append(cEnterpriseServicemodulesSubDir);
        lServicemoduleDirectoryName.append(File.separator);
        lServicemoduleDirectoryName.append(lTokenizer.nextToken()); // Servicemodulemodule
        return lServicemoduleDirectoryName.toString();
    }

    // Helper. Returns fully qualified directory where type template details can be found
    private static String getTypeTemplateDirectory(String pTypeTemplateRef) throws PSException
    {
    // Typetemplate may be in public use packages (ref must begin with dot in this case)
    // Otherwise TypeTemplateRef consists of three or more parts - enterprise name . system name [. sub package name] . typetemplate name
    if (pTypeTemplateRef.startsWith("."))
    {
      // Public typetemplate, convert its name back to the directory name
      // and try on a path until we will get it
      String lTypeTemplateSubdirectoryName = StringUtils.replace(pTypeTemplateRef,".", File.separator);
      String[] lMetaLibPath = getPublicMetaModelPath();
      for (int i = 0; i < lMetaLibPath.length; i++)
      {
        String lProspectiveDirectoryPath = lMetaLibPath[i] + sTypeTemplateMetaLibSubDir + lTypeTemplateSubdirectoryName;
        File lProspectiveDirectory = new File(lProspectiveDirectoryPath);
        if (lProspectiveDirectory.exists() && lProspectiveDirectory.isDirectory())
          return lProspectiveDirectoryPath; // Found first hit
      }
      return null;
    }
    // Enterprise typetemplate below this point
    String lProspectiveDirectoryPath = suggestEnterpriseTypeTemplateDirectory(pTypeTemplateRef);
    File lProspectiveDirectory = new File(lProspectiveDirectoryPath);
    if (lProspectiveDirectory.exists() && lProspectiveDirectory.isDirectory())
      return lProspectiveDirectoryPath; // Found first hit
    return null;
    }

  // Helper. Returns prospective fully qualified directory where typetemplate details can be found
  // only works for enterprise typetemplates
  private static String suggestEnterpriseTypeTemplateDirectory(String pTypeTemplateRef) throws PSException
  {
    // Typetemplate may be in public use packages (ref must begin with dot in this case)
    // Otherwise TypetemplateRef consists of three or more parts - enterprise name . system name [. sub package name] . typetemplate name
    if (pTypeTemplateRef.startsWith("."))
      throw new PSIllegalArgumentException("Unable to suggest directory name for the public typetemplate. TypeTemplateRef: " + pTypeTemplateRef);
    // Enterprise typetemplate below this point
    StringBuffer lTypeTemplateDirectoryName = new StringBuffer();
    StringTokenizer lTokenizer = new StringTokenizer(pTypeTemplateRef,".",false);
    int lTokenCount = lTokenizer.countTokens();
    if (lTokenCount < 3)
      throw new PSIllegalArgumentException("Invalid TypeTemplateRef: " + pTypeTemplateRef);
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    lTypeTemplateDirectoryName.append(cEnterpriseRootDir);
    lTypeTemplateDirectoryName.append(File.separator);
    lTypeTemplateDirectoryName.append(lEnterpriseName);
    lTypeTemplateDirectoryName.append(File.separator);
    lTypeTemplateDirectoryName.append(cEnterpriseSystemsSubDir);
    lTypeTemplateDirectoryName.append(File.separator);
    lTypeTemplateDirectoryName.append(lSystemName);
    lTypeTemplateDirectoryName.append(File.separator);
    lTypeTemplateDirectoryName.append(cEnterpriseDatatypesSubDir);
    // Append posible subdirectories
    if (lTokenCount == 3)
    {
      lTypeTemplateDirectoryName.append(File.separator);
      lTypeTemplateDirectoryName.append("-");
    }
    else
    {
      for (int i = 1; i < lTokenCount - 1; i++)
      {
        lTypeTemplateDirectoryName.append(File.separator);
        lTypeTemplateDirectoryName.append(lTokenizer.nextToken());
      }
    }
    lTypeTemplateDirectoryName.append(File.separator);
    lTypeTemplateDirectoryName.append(cTypetemplatesSubDir);
    lTypeTemplateDirectoryName.append(File.separator);
    lTypeTemplateDirectoryName.append(lTokenizer.nextToken());
    return lTypeTemplateDirectoryName.toString();
  }


    /** Returns Entity def or null if none found */
    public static EntityDefType getEntity(String pEntityRef) throws PSException
    {
        // First see if we have this object already
    EntityDefType lRet = (EntityDefType)cDOMObjectsCache.get(pEntityRef + ";" + EntityDefType.class.getName());
        if (lRet == null)
        {
            // EntityRef always consists of four parts - enterprise name . system name . domain name . entity name
            StringTokenizer lTokenizer = new StringTokenizer(pEntityRef,".",false);
            if (lTokenizer.countTokens() != 4)
                throw new PSException("Invalid EntityRef: " + pEntityRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lDomainName = lTokenizer.nextToken();
            String lEntityName = lTokenizer.nextToken();
            DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
            List lEntities = lDomainDef.getEntityDefList().getEntityDef();
            Iterator lIter = lEntities.iterator();
            while (lIter.hasNext())
            {
                EntityDefType lEntityDef = (EntityDefType)lIter.next();
                if (lEntityDef.getEntityRef().equals(pEntityRef))
                {
                    cDOMObjectsCache.put(pEntityRef + ";" + EntityDefType.class.getName(),lRet = lEntityDef);
                    break;
                }
            }
        }
        return lRet;
    }

    /** Returns Report def or null if none found */
    public static ReportDefType getReport(String pReportRef) throws PSException
    {
        // First see if we have this object already
        ReportDefType lRet = (ReportDefType)cDOMObjectsCache.get(pReportRef + ";" + ReportDefType.class.getName());
        if (lRet == null)
        {
            // ReportRef always consists of four parts - enterprise name . system name . domain name . report name
            StringTokenizer lTokenizer = new StringTokenizer(pReportRef,".",false);
            if (lTokenizer.countTokens() != 4)
                throw new PSException("Invalid ReportRef: " + pReportRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lDomainName = lTokenizer.nextToken();
            String lReportName = lTokenizer.nextToken();
            DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
            List lReports = lDomainDef.getReportDefList().getReportDef();
            Iterator lIter = lReports.iterator();
            while (lIter.hasNext())
            {
                ReportDefType lReportDef = (ReportDefType)lIter.next();
                if (lReportDef.getReportRef().equals(pReportRef))
                {
                    cDOMObjectsCache.put(pReportRef + ";" + ReportDefType.class.getName(),lRet = lReportDef);
                    break;
                }
            }
        }
        return lRet;
    }

    /** Returns Service def or null if none found */
    public static ServiceDefType getService(String pServiceRef) throws PSException
    {
        // First see if we have this object already
        ServiceDefType lRet = (ServiceDefType)cDOMObjectsCache.get(pServiceRef + ";" + ServiceDefType.class.getName());
        if (lRet == null)
        {
            // ServiceRef always consists of four parts - enterprise name . system name . servicemodule name . service name
            StringTokenizer lTokenizer = new StringTokenizer(pServiceRef,".",false);
            if (lTokenizer.countTokens() != 4)
                throw new PSException("Invalid ServiceRef: " + pServiceRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lServicemoduleName = lTokenizer.nextToken();
            String lServiceName = lTokenizer.nextToken();
            ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
            if (lServicemoduleDef == null)
                return null; // Servicemodule does not exist, so is service
            List lServices = lServicemoduleDef.getServiceDefList().getServiceDef();
            Iterator lIter = lServices.iterator();
            while (lIter.hasNext())
            {
                ServiceDefType lServiceDef = (ServiceDefType)lIter.next();
                if (lServiceDef.getServiceRef().equals(pServiceRef))
                {
                    cDOMObjectsCache.put(pServiceRef + ";" + ServiceDefType.class.getName(),lRet = lServiceDef);
                    break;
                }
            }
        }
        return lRet;
    }

    /** Returns Servicemodule def or null if none found */
    public static ServicemoduleDefType getServicemodule(String pServicemoduleRef) throws PSException
    {
        // First see if we have this object already
        ServicemoduleDefType lRet = (ServicemoduleDefType)cDOMObjectsCache.get(pServicemoduleRef + ";" + ServicemoduleDefType.class.getName());
        if (lRet == null)
        {
            // ServciemoduleRef always consists of three parts - enterprise name . system name . serviemodule name
            StringTokenizer lTokenizer = new StringTokenizer(pServicemoduleRef,".",false);
            if (lTokenizer.countTokens() != 3)
                throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lServicemoduleName = lTokenizer.nextToken();
            String lServicemoduleFileName = cEnterpriseRootDir + File.separator +
                                         lEnterpriseName + File.separator +
                                         cEnterpriseSystemsSubDir + File.separator +
                                         lSystemName + File.separator +
                                         cEnterpriseServicemodulesSubDir + File.separator +
                                         lServicemoduleName + "ServicemoduleDescriptor.xml";
            File lServicemoduleFile = new File(lServicemoduleFileName);
            if (lServicemoduleFile.exists() == false)
                return null;
            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lServicemoduleFileName);
                if (lInputStream != null)
                {
                    if((lRet = (ServicemoduleDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getServicemoduleRef().equals(pServicemoduleRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between ServicemoduleRef stored in file and the one implied by its location. ServicemoduleRef : " + lRet.getServicemoduleRef() + ", Location : " + lServicemoduleFileName);
                        cDOMObjectsCache.put(pServicemoduleRef + ";" + ServicemoduleDefType.class.getName(),lRet);
                    }
                }
            }
            catch(JAXBException e)
            {
                throw new PSDataSourceOperationInvocationException(e);
            }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** Inserts new Servicemodule def */
    public static void insertServicemodule(ServicemoduleDefType pServicemoduleDef) throws PSException
    {
      try
      {
      try
      {
        getValidator().validate(pServicemoduleDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Servicemodule definition validation exception. ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef(), e);
      }
        
          // ServciemoduleRef always consists of three parts - enterprise name . system name . serviemodule name
          StringTokenizer lTokenizer = new StringTokenizer(pServicemoduleDef.getServicemoduleRef(),".",false);
          if (lTokenizer.countTokens() != 3)
              throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef());
          String lEnterpriseName = lTokenizer.nextToken();
          String lSystemName = lTokenizer.nextToken();
          String lServicemoduleName = lTokenizer.nextToken();
          String lServicemoduleFileName = cEnterpriseRootDir + File.separator +
                                       lEnterpriseName + File.separator +
                                       cEnterpriseSystemsSubDir + File.separator +
                                       lSystemName + File.separator +
                                       cEnterpriseServicemodulesSubDir + File.separator +
                                       lServicemoduleName + "ServicemoduleDescriptor.xml";
          File lServicemoduleFile = new File(lServicemoduleFileName);
          if (lServicemoduleFile.exists() == true)
              throw new PSException("File " + lServicemoduleFileName + " already exists. Unable to insert servicemodule. ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef());
          // Ensure that system exists
          File lSystemServicemodulesDirectoryFile = lServicemoduleFile.getParentFile();
          File lSystemDirectoryFile = lSystemServicemodulesDirectoryFile.getParentFile();
          if (lSystemDirectoryFile.exists() == false)
             throw new PSException("Attempt to insert Servicemodule into non existant System. ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef());
          DirectoryUtils.ensureThereIsDirectory(lSystemServicemodulesDirectoryFile.getAbsolutePath());
          // Clean up the cache prior to saving the new file
          cDOMObjectsCache.remove(pServicemoduleDef.getServicemoduleRef() + ";" + ServicemoduleDefType.class.getName());
          FileOutputStream lFileOutputStream = null;
          try
          {
              lFileOutputStream = new FileOutputStream(lServicemoduleFile);
        getMarshaller().marshal(pServicemoduleDef,lFileOutputStream);
              lFileOutputStream.flush();
              lFileOutputStream.close();
              lFileOutputStream = null;
              cDOMObjectsCache.put(pServicemoduleDef.getServicemoduleRef() + ";" + ServicemoduleDefType.class.getName(),pServicemoduleDef);
          }
          catch(IOException e)
          {
              throw new PSException("Caught exception while writing file : " + lServicemoduleFileName, e);
          }
          finally
          {
              try
              {
                  if (lFileOutputStream != null)
                      lFileOutputStream.close();
              }
              catch(IOException e)
              {
              }
          }
      }          
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    }

  /** Inserts new Enterprise def */
  public static void insertEnterprise(EnterpriseDefType pEnterpriseDef) throws PSException
  {
    try
    {
      try
      {
        getValidator().validate(pEnterpriseDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Enterprise definition validation exception. EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef(), e);
      }
        
      // ServciemoduleRef always consists of three parts - enterprise name . system name . serviemodule name
      StringTokenizer lTokenizer = new StringTokenizer(pEnterpriseDef.getEnterpriseRef(),".",false);
      if (lTokenizer.countTokens() != 1)
        throw new PSException("Invalid EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef());
      String lEnterpriseName = lTokenizer.nextToken();
      String lEnterpriseFileName = cEnterpriseRootDir + File.separator +
                     lEnterpriseName + File.separator + "Descriptor.xml";
      File lEnterpriseFile = new File(lEnterpriseFileName);
      if (lEnterpriseFile.exists() == true)
        throw new PSException("File " + lEnterpriseFileName + " already exists. Unable to insert enterprise. EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef());
      // Ensure that system exists
      File lEnterpriseDirectoryFile = lEnterpriseFile.getParentFile();
      DirectoryUtils.ensureThereIsDirectory(lEnterpriseDirectoryFile.getAbsolutePath());
      // Clean up the cache prior to saving the new file
      cDOMObjectsCache.remove(pEnterpriseDef.getEnterpriseRef() + ";" + EnterpriseDefType.class.getName());
      FileOutputStream lFileOutputStream = null;
      try
      {
        lFileOutputStream = new FileOutputStream(lEnterpriseFile);
        getMarshaller().marshal(pEnterpriseDef,lFileOutputStream);
        lFileOutputStream.flush();
        lFileOutputStream.close();
        lFileOutputStream = null;
        cDOMObjectsCache.put(pEnterpriseDef.getEnterpriseRef() + ";" + EnterpriseDefType.class.getName(),pEnterpriseDef);
      }
      catch(IOException e)
      {
        throw new PSException("Caught exception while writing file : " + lEnterpriseFileName, e);
      }
      finally
      {
        try
        {
          if (lFileOutputStream != null)
            lFileOutputStream.close();
        }
        catch(IOException e)
        {
        }
      }
    }          
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
  }

  /** Inserts new system def */
  public static void insertSystem(SystemDefType pSystemDef) throws PSException
  {
    try
    {
      try
      {
        getValidator().validate(pSystemDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("System definition validation exception. SystemRef: " + pSystemDef.getSystemRef(), e);
      }
      String lSystemDirectoryName = getSystemDirectory(pSystemDef.getSystemRef());
      File lSystemDirectory = new File(lSystemDirectoryName);
      if (lSystemDirectory.exists())
        throw new PSException("Directory " + lSystemDirectoryName + " already exists. Unable to create system. SystemRef: " + pSystemDef.getSystemRef());
      DirectoryUtils.ensureThereIsDirectory(lSystemDirectory.getAbsolutePath());
      String lSystemFileName = lSystemDirectoryName + File.separator + "Descriptor.xml";
      File lSystemFile = new File(lSystemFileName);
      FileOutputStream lFileOutputStream = null;
      try
      {
        lFileOutputStream = new FileOutputStream(lSystemFile);
        getMarshaller().marshal(pSystemDef,lFileOutputStream);
        lFileOutputStream.flush();
        lFileOutputStream.close();
        lFileOutputStream = null;
        cDOMObjectsCache.put(pSystemDef.getSystemRef() + ";" + SystemDefType.class.getName(),pSystemDef);
      }
      catch(IOException e)
      {
        throw new PSException("Caught exception while writing file : " + lSystemFileName, e);
      }
      finally
      {
        try
        {
          if (lFileOutputStream != null)
            lFileOutputStream.close();
        }
        catch(IOException e)
        {
        }
      }
    }          
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
  }

    /** Inserts new service def */
    public static void insertService(ServiceDefType pServiceDef) throws PSException
    {
    try
    {
      getValidator().validate(pServiceDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Service definition validation exception. ServiceRef: " + pServiceDef.getServiceRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
     
        if (getService(pServiceDef.getServiceRef()) != null)
           throw new PSException("Attempt to insert alredy existing Service into Servicemodule. ServiceRef: " + pServiceDef.getServiceRef());
        // ServiceRef always consists of four parts - enterprise name . system name . servicemodule name . service name
        StringTokenizer lTokenizer = new StringTokenizer(pServiceDef.getServiceRef(),".",false);
        if (lTokenizer.countTokens() != 4)
            throw new PSException("Invalid ServiceRef: " + pServiceDef.getServiceRef());
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lServiceName = lTokenizer.nextToken();
        ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
        if (lServicemoduleDef == null)
           throw new PSException("Attempt to insert Service into Servicemodule, which does not exists. ServiceRef: " + pServiceDef.getServiceRef());
        lServicemoduleDef.getServiceDefList().getServiceDef().add(pServiceDef);
        updateServicemodule(lServicemoduleDef);
        cDOMObjectsCache.put(pServiceDef.getServiceRef() + ";" + ServiceDefType.class.getName(),pServiceDef);
    }

    /** Updates service details on storage */
    public static void updateService(ServiceDefType pServiceDef) throws PSException
    {
    try
    {
      getValidator().validate(pServiceDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Service definition validation exception. ServiceRef: " + pServiceDef.getServiceRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
     
        ServiceDefType lCurrentCopy = getService(pServiceDef.getServiceRef());
        if (lCurrentCopy == null)
           throw new PSException("Attempt to update Service, which does not exists. ServiceRef: " + pServiceDef.getServiceRef());
        // ServiceRef always consists of four parts - enterprise name . system name . servicemodule name . service name
        StringTokenizer lTokenizer = new StringTokenizer(pServiceDef.getServiceRef(),".",false);
        if (lTokenizer.countTokens() != 4)
            throw new PSException("Invalid ServiceRef: " + pServiceDef.getServiceRef());
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lServiceName = lTokenizer.nextToken();
        ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
        if (lServicemoduleDef == null)
           throw new PSException("Attempt to update Service into Servicemodule, which does not exists. ServiceRef: " + pServiceDef.getServiceRef());
        cDOMObjectsCache.remove(pServiceDef.getServiceRef() + ";" + ServiceDefType.class.getName());
        if (!lServicemoduleDef.getServiceDefList().getServiceDef().remove(lCurrentCopy))
      throw new PSUnexpectedProgramConditionException("Remove of previous version of the service definition has failed. ServiceRef: " + pServiceDef.getServiceRef());
        lServicemoduleDef.getServiceDefList().getServiceDef().add(pServiceDef);
        updateServicemodule(lServicemoduleDef);
        cDOMObjectsCache.put(pServiceDef.getServiceRef() + ";" + ServiceDefType.class.getName(),pServiceDef);
    }

    /** Returns Structure def or null if none found */
    public static StructureDefType getStructure(String pStructureRef) throws PSException
    {
        // First see if we have this object already
        StructureDefType lRet = (StructureDefType)cDOMObjectsCache.get(pStructureRef + ";" + StructureDefType.class.getName());
        if (lRet == null)
        {
            // StructureRef always consists of four parts - enterprise name . system name . servicemodule name . structure name
            StringTokenizer lTokenizer = new StringTokenizer(pStructureRef,".",false);
            if (lTokenizer.countTokens() != 4)
                throw new PSException("Invalid StructureRef: " + pStructureRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lServicemoduleName = lTokenizer.nextToken();
            String lStructureName = lTokenizer.nextToken();
            String lServicemoduleRef = lEnterpriseName + "." + lSystemName + "." + lServicemoduleName; 
            ServicemoduleDefType lServicemoduleDef = getServicemodule(lServicemoduleRef);
      if (lServicemoduleDef == null)
        throw new PSException("Servicemodule not found. ServicemoduleRef: " + lServicemoduleRef);
            List lStructures = lServicemoduleDef.getStructureDefList().getStructureDef();
            Iterator lIter = lStructures.iterator();
            while (lIter.hasNext())
            {
                StructureDefType lStructureDef = (StructureDefType)lIter.next();
                if (lStructureDef.getStructureRef().equals(pStructureRef))
                {
                    cDOMObjectsCache.put(pStructureRef + ";" + StructureDefType.class.getName(),lRet = lStructureDef);
                    break;
                }
            }
        }
        return lRet;
    }

    /** Returns Message def or null if none found */
    public static MessageDefType getMessage(String pMessageRef) throws PSException
    {
        // First see if we have this object already
        MessageDefType lRet = (MessageDefType)cDOMObjectsCache.get(pMessageRef + ";" + MessageDefType.class.getName());
        if (lRet == null)
        {
            // MessageRef always consists of four parts - enterprise name . system name . servicemodule name . message name
            StringTokenizer lTokenizer = new StringTokenizer(pMessageRef,".",false);
            if (lTokenizer.countTokens() != 4)
                throw new PSException("Invalid MessageRef: " + pMessageRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lServicemoduleName = lTokenizer.nextToken();
            String lMessageName = lTokenizer.nextToken();
            ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
            List lMessages = lServicemoduleDef.getMessageDefList().getMessageDef();
            Iterator lIter = lMessages.iterator();
            while (lIter.hasNext())
            {
                MessageDefType lMessageDef = (MessageDefType)lIter.next();
                if (lMessageDef.getMessageRef().equals(pMessageRef))
                {
                    cDOMObjectsCache.put(pMessageRef + ";" + MessageDefType.class.getName(),lRet = lMessageDef);
                    break;
                }
            }
        }
        return lRet;
    }

    /** Inserts new structure def */
    public static void insertStructure(StructureDefType pStructureDef) throws PSException
    {
    try
    {
      getValidator().validate(pStructureDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Structure definition validation exception. StructureRef : " + pStructureDef.getStructureRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
     
        if (getStructure(pStructureDef.getStructureRef()) != null)
           throw new PSException("Attempt to insert alredy existing Structure into Servicemodule. StructureRef: " + pStructureDef.getStructureRef());
        // StructureRef always consists of four parts - enterprise name . system name . servicemodule name . structure name
        StringTokenizer lTokenizer = new StringTokenizer(pStructureDef.getStructureRef(),".",false);
        if (lTokenizer.countTokens() != 4)
            throw new PSException("Invalid StructureRef: " + pStructureDef.getStructureRef());
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lStructureName = lTokenizer.nextToken();
        ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
        if (lServicemoduleDef == null)
           throw new PSException("Attempt to insert Structure into Servicemodule, which does not exists. StructureRef: " + pStructureDef.getStructureRef());
        lServicemoduleDef.getStructureDefList().getStructureDef().add(pStructureDef);
        updateServicemodule(lServicemoduleDef);
        cDOMObjectsCache.put(pStructureDef.getStructureRef() + ";" + StructureDefType.class.getName(),pStructureDef);
    }

    /** Inserts new message def */
    public static void insertMessage(MessageDefType pMessageDef) throws PSException
    {
    try
    {
      getValidator().validate(pMessageDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Message definition validation exception. MessageRef : " + pMessageDef.getMessageRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
        if (getMessage(pMessageDef.getMessageRef()) != null)
           throw new PSException("Attempt to insert alredy existing Message into Servicemodule. MessageRef: " + pMessageDef.getMessageRef());
        // MessageRef always consists of four parts - enterprise name . system name . servicemodule name . message name
        StringTokenizer lTokenizer = new StringTokenizer(pMessageDef.getMessageRef(),".",false);
        if (lTokenizer.countTokens() != 4)
            throw new PSException("Invalid MessageRef: " + pMessageDef.getMessageRef());
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lMessageName = lTokenizer.nextToken();
        ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
        if (lServicemoduleDef == null)
           throw new PSException("Attempt to insert Message into Servicemodule, which does not exists. MessageRef: " + pMessageDef.getMessageRef());
        lServicemoduleDef.getMessageDefList().getMessageDef().add(pMessageDef);
        updateServicemodule(lServicemoduleDef);
        cDOMObjectsCache.put(pMessageDef.getMessageRef() + ";" + MessageDefType.class.getName(),pMessageDef);
    }

    /** Updates structure details on storage */
    public static void updateStructure(StructureDefType pStructureDef) throws PSException
    {
    try
    {
      getValidator().validate(pStructureDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Structure definition validation exception. StructureRef : " + pStructureDef.getStructureRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
        StructureDefType lCurrentCopy = getStructure(pStructureDef.getStructureRef());
        if (lCurrentCopy == null)
           throw new PSException("Attempt to update Structure, which does not exists. StructureRef: " + pStructureDef.getStructureRef());
        // StructureRef always consists of four parts - enterprise name . system name . servicemodule name . service name
        StringTokenizer lTokenizer = new StringTokenizer(pStructureDef.getStructureRef(),".",false);
        if (lTokenizer.countTokens() != 4)
            throw new PSException("Invalid StructureRef: " + pStructureDef.getStructureRef());
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lStructureName = lTokenizer.nextToken();
        ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
        if (lServicemoduleDef == null)
           throw new PSException("Attempt to update Structure into Servicemodule, which does not exists. StructureRef: " + pStructureDef.getStructureRef());
        cDOMObjectsCache.remove(pStructureDef.getStructureRef() + ";" + StructureDefType.class.getName());
        if (!lServicemoduleDef.getStructureDefList().getStructureDef().remove(lCurrentCopy))
      throw new PSUnexpectedProgramConditionException("Remove of previous version of the structure definition has failed. StructureRef: " + pStructureDef.getStructureRef());
        lServicemoduleDef.getStructureDefList().getStructureDef().add(pStructureDef);
        updateServicemodule(lServicemoduleDef);
        cDOMObjectsCache.put(pStructureDef.getStructureRef() + ";" + StructureDefType.class.getName(),pStructureDef);
    }

    /** Updates message details on storage */
    public static void updateMessage(MessageDefType pMessageDef) throws PSException
    {
    try
    {
      getValidator().validate(pMessageDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Message definition validation exception. MessageRef : " + pMessageDef.getMessageRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
     
        MessageDefType lCurrentCopy = getMessage(pMessageDef.getMessageRef());
        if (lCurrentCopy == null)
           throw new PSException("Attempt to update Message, which does not exists. MessageRef: " + pMessageDef.getMessageRef());
        // MessageRef always consists of four parts - enterprise name . system name . servicemodule name . message name
        StringTokenizer lTokenizer = new StringTokenizer(pMessageDef.getMessageRef(),".",false);
        if (lTokenizer.countTokens() != 4)
            throw new PSException("Invalid MessageRef: " + pMessageDef.getMessageRef());
        String lEnterpriseName = lTokenizer.nextToken();
        String lSystemName = lTokenizer.nextToken();
        String lServicemoduleName = lTokenizer.nextToken();
        String lMessageName = lTokenizer.nextToken();
        ServicemoduleDefType lServicemoduleDef = getServicemodule(lEnterpriseName + "." + lSystemName + "." + lServicemoduleName);
        if (lServicemoduleDef == null)
           throw new PSException("Attempt to update Message into Servicemodule, which does not exists. MessageRef: " + pMessageDef.getMessageRef());
        cDOMObjectsCache.remove(pMessageDef.getMessageRef() + ";" + MessageDefType.class.getName());
    if (!lServicemoduleDef.getMessageDefList().getMessageDef().remove(lCurrentCopy))
      throw new PSUnexpectedProgramConditionException("Remove of previous version of the message definition has failed. MessageRef: " + pMessageDef.getMessageRef());
        lServicemoduleDef.getMessageDefList().getMessageDef().add(pMessageDef);
        updateServicemodule(lServicemoduleDef);
        cDOMObjectsCache.put(pMessageDef.getMessageRef() + ";" + MessageDefType.class.getName(),pMessageDef);
    }

  /** Updates entity details on storage */
  public static void updateEntity(EntityDefType pEntityDef) throws PSException
  {
    try
    {
      getValidator().validate(pEntityDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Entity definition validation exception. EntityRef: " + pEntityDef.getEntityRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    EntityDefType lCurrentCopy = getEntity(pEntityDef.getEntityRef());
    if (lCurrentCopy == null)
       throw new PSException("Attempt to update Entity, which does not exists. EntityRef: " +  pEntityDef.getEntityRef());
    // EntityRef always consists of four parts - enterprise name . system name . domain name . entity name
    StringTokenizer lTokenizer = new StringTokenizer(pEntityDef.getEntityRef(),".",false);
    if (lTokenizer.countTokens() != 4)
      throw new PSIllegalArgumentException("Invalid EntityRef: " + pEntityDef.getEntityRef());
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    String lDomainName = lTokenizer.nextToken();
    String lEntityName = lTokenizer.nextToken();
    DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
    if (lDomainDef == null)
       throw new PSException("Attempt to update Entity into Domain, which does not exists. EntityRef: " + pEntityDef.getEntityRef());
    cDOMObjectsCache.remove(pEntityDef.getEntityRef() + ";" + EntityDefType.class.getName());
    if (!lDomainDef.getEntityDefList().getEntityDef().remove(lCurrentCopy))
      throw new PSUnexpectedProgramConditionException("Remove of previous version of the entity definition has failed. EntityRef: " + pEntityDef.getEntityRef());
    lDomainDef.getEntityDefList().getEntityDef().add(pEntityDef);
    updateDomain(lDomainDef);
    cDOMObjectsCache.put(pEntityDef.getEntityRef() + ";" + EntityDefType.class.getName(),pEntityDef);
  }

  /** Updates association details on storage */
  public static void updateAssociation(AssociationDefType pAssociationDef) throws PSException
  {
    try
    {
      getValidator().validate(pAssociationDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Association definition validation exception. AssociationRef: " + pAssociationDef.getAssociationRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    AssociationDefType lCurrentCopy = getAssociation(pAssociationDef.getAssociationRef());
    if (lCurrentCopy == null)
       throw new PSException("Attempt to update Association, which does not exists. AssociationRef: " +  pAssociationDef.getAssociationRef());
    // AssociationRef always consists of four parts - enterprise name . system name . domain name . association name
    StringTokenizer lTokenizer = new StringTokenizer(pAssociationDef.getAssociationRef(),".",false);
    if (lTokenizer.countTokens() != 4)
      throw new PSIllegalArgumentException("Invalid AssociationRef: " + pAssociationDef.getAssociationRef());
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    String lDomainName = lTokenizer.nextToken();
    String lAssociationName = lTokenizer.nextToken();
    DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
    if (lDomainDef == null)
       throw new PSException("Attempt to update Association into Domain, which does not exists. AssociationRef: " + pAssociationDef.getAssociationRef());
    cDOMObjectsCache.remove(pAssociationDef.getAssociationRef() + ";" + AssociationDefType.class.getName());
    if (!lDomainDef.getAssociationDefList().getAssociationDef().remove(lCurrentCopy))
      throw new PSUnexpectedProgramConditionException("Remove of previous version of the association definition has failed. AssociationRef: " + pAssociationDef.getAssociationRef());
    lDomainDef.getAssociationDefList().getAssociationDef().add(pAssociationDef);
    updateDomain(lDomainDef);
    cDOMObjectsCache.put(pAssociationDef.getAssociationRef() + ";" + AssociationDefType.class.getName(),pAssociationDef);
  }

  /** Updates entity details on storage */
  public static void insertEntity(EntityDefType pEntityDef) throws PSException
  {
    try
    {
      getValidator().validate(pEntityDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Entity definition validation exception. EntityRef: " + pEntityDef.getEntityRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    if (getEntity(pEntityDef.getEntityRef()) != null)
       throw new PSException("Attempt to insert alredy existing Entity into Domain. EntityRef: " + pEntityDef.getEntityRef());
    // EntityRef always consists of four parts - enterprise name . system name . domain name . structure name
    StringTokenizer lTokenizer = new StringTokenizer(pEntityDef.getEntityRef(),".",false);
    if (lTokenizer.countTokens() != 4)
      throw new PSException("Invalid EntityRef: " + pEntityDef.getEntityRef());
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    String lDomainName = lTokenizer.nextToken();
    String lEntityName = lTokenizer.nextToken();
    DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
    if (lDomainDef == null)
       throw new PSException("Attempt to insert Entity into non-existant Domain. EntityRef: " + pEntityDef.getEntityRef());
    lDomainDef.getEntityDefList().getEntityDef().add(pEntityDef);
    updateDomain(lDomainDef);
    cDOMObjectsCache.put(pEntityDef.getEntityRef() + ";" + EntityDefType.class.getName(),pEntityDef);
  }

  /** Updates association details on storage */
  public static void insertAssociation(AssociationDefType pAssociationDef) throws PSException
  {
    try
    {
      getValidator().validate(pAssociationDef);
    }
    catch(ValidationException  e)
    {
      throw new PSContentConstraintViolationException("Association definition validation exception. AssociationRef: " + pAssociationDef.getAssociationRef(), e);
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    if (getAssociation(pAssociationDef.getAssociationRef()) != null)
       throw new PSException("Attempt to insert alredy existing Association into Domain. AssociationRef: " + pAssociationDef.getAssociationRef());
    // AssociationRef always consists of four parts - enterprise name . system name . domain name . structure name
    StringTokenizer lTokenizer = new StringTokenizer(pAssociationDef.getAssociationRef(),".",false);
    if (lTokenizer.countTokens() != 4)
      throw new PSException("Invalid AssociationRef: " + pAssociationDef.getAssociationRef());
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    String lDomainName = lTokenizer.nextToken();
    String lAssociationName = lTokenizer.nextToken();
    DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
    if (lDomainDef == null)
       throw new PSException("Attempt to insert Association into non-existant Domain. AssociationRef: " + pAssociationDef.getAssociationRef());
    lDomainDef.getAssociationDefList().getAssociationDef().add(pAssociationDef);
    updateDomain(lDomainDef);
    cDOMObjectsCache.put(pAssociationDef.getAssociationRef() + ";" + AssociationDefType.class.getName(),pAssociationDef);
  }

  /** Deletes entity details from storage */
  public static void deleteEntity(String pEntityRef) throws PSException
  {
    EntityDefType lEntityDefToDelete = getEntity(pEntityRef);   
    if (lEntityDefToDelete == null)
      throw new PSUnexpectedProgramConditionException("Attempt to delete entity, which does not exists. EntityRef: " + pEntityRef);
    // EntityRef always consists of four parts - enterprise name . system name . domain name . entity name
    StringTokenizer lTokenizer = new StringTokenizer(pEntityRef,".",false);
    if (lTokenizer.countTokens() != 4)
      throw new PSIllegalArgumentException("Invalid EntityRef: " + pEntityRef);
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    String lDomainName = lTokenizer.nextToken();
    String lEntityName = lTokenizer.nextToken();
    DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
    if (lDomainDef == null)
       throw new PSException("Attempt to delete entity from Domain, which does not exists. EntityRef: " + pEntityRef);
    lDomainDef.getEntityDefList().getEntityDef().remove(lEntityDefToDelete);
    cDOMObjectsCache.remove(pEntityRef + ";" + EntityDefType.class.getName());
    updateDomain(lDomainDef);
  }


  /** Deletes association details from storage */
  public static void deleteAssociation(String pAssociationRef) throws PSException
  {
    AssociationDefType lAssociationDefToDelete = getAssociation(pAssociationRef);
    if (lAssociationDefToDelete == null)
      throw new PSUnexpectedProgramConditionException("Attempt to delete association, which does not exists. AssociationRef: " + pAssociationRef);
    // AssociationRef always consists of four parts - enterprise name . system name . domain name . association name
    StringTokenizer lTokenizer = new StringTokenizer(pAssociationRef,".",false);
    if (lTokenizer.countTokens() != 4)
      throw new PSIllegalArgumentException("Invalid EntityRef: " + pAssociationRef);
    String lEnterpriseName = lTokenizer.nextToken();
    String lSystemName = lTokenizer.nextToken();
    String lDomainName = lTokenizer.nextToken();
    String lAssociationName = lTokenizer.nextToken();
    DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
    if (lDomainDef == null)
       throw new PSException("Attempt to delete association from Domain, which does not exists. AssociationRef: " + pAssociationRef);
    lDomainDef.getAssociationDefList().getAssociationDef().remove(lAssociationDefToDelete);
    cDOMObjectsCache.remove(pAssociationRef + ";" + AssociationDefType.class.getName());
    updateDomain(lDomainDef);
  }

    /** Updates servicemodule details on storage */
    public static void updateServicemodule(ServicemoduleDefType pServicemoduleDef) throws PSException
    {
      try
      {
      try
      {
        getValidator().validate(pServicemoduleDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Servicemodule definition validation exception. ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef(), e);
      }
          // ServciemoduleRef always consists of three parts - enterprise name . system name . serviemodule name
          StringTokenizer lTokenizer = new StringTokenizer(pServicemoduleDef.getServicemoduleRef(),".",false);
          if (lTokenizer.countTokens() != 3)
              throw new PSException("Invalid ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef());
          String lEnterpriseName = lTokenizer.nextToken();
          String lSystemName = lTokenizer.nextToken();
          String lServicemoduleName = lTokenizer.nextToken();
          String lServicemoduleFileName = cEnterpriseRootDir + File.separator +
                                       lEnterpriseName + File.separator +
                                       cEnterpriseSystemsSubDir + File.separator +
                                       lSystemName + File.separator +
                                       cEnterpriseServicemodulesSubDir + File.separator +
                                       lServicemoduleName + "ServicemoduleDescriptor.xml";
          File lServicemoduleFile = new File(lServicemoduleFileName);
          if (lServicemoduleFile.exists() == false)
              throw new PSException("File " + lServicemoduleFileName + " does not exist. Unable to update servicemodule. ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef());
          if (lServicemoduleFile.canWrite() == false)
              throw new PSException("File " + lServicemoduleFileName + " is read-only. Unable to update servicemodule. ServicemoduleRef: " + pServicemoduleDef.getServicemoduleRef());
          // Clean up the cache prior to saving the new file
          cDOMObjectsCache.remove(pServicemoduleDef.getServicemoduleRef() + ";" + ServicemoduleDefType.class.getName());
          FileOutputStream lFileOutputStream = null;
          try
          {
              lFileOutputStream = new FileOutputStream(lServicemoduleFile);
        getMarshaller().marshal(pServicemoduleDef,lFileOutputStream);
              lFileOutputStream.flush();
              lFileOutputStream.close();
              lFileOutputStream = null;
              cDOMObjectsCache.put(pServicemoduleDef.getServicemoduleRef() + ";" + ServicemoduleDefType.class.getName(),pServicemoduleDef);
          }
          catch(IOException e)
          {
              throw new PSException("Caught exception while writing file : " + lServicemoduleFileName, e);
          }
          finally
          {
              try
              {
                  if (lFileOutputStream != null)
                      lFileOutputStream.close();
              }
              catch(IOException e)
              {
              }
          }
      }          
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    }

  /** Updates enterprise details on storage */
  public static void updateEnterprise(EnterpriseDefType pEnterpriseDef) throws PSException
  {
    try
    {
      try
      {
        getValidator().validate(pEnterpriseDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Enterprise definition validation exception. EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef(), e);
      }
      // ServciemoduleRef always consists of three parts - enterprise name . system name . serviemodule name
      StringTokenizer lTokenizer = new StringTokenizer(pEnterpriseDef.getEnterpriseRef(),".",false);
      if (lTokenizer.countTokens() != 1)
        throw new PSException("Invalid EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef());
      String lEnterpriseName = lTokenizer.nextToken();
      String lEnterpriseFileName = cEnterpriseRootDir + File.separator +
                     lEnterpriseName + File.separator + "Descriptor.xml";
      File lEnterpriseFile = new File(lEnterpriseFileName);
      if (lEnterpriseFile.exists() == false)
        throw new PSException("File " + lEnterpriseFileName + " does not exist. Unable to update enterprise. EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef());
      if (lEnterpriseFile.canWrite() == false)
        throw new PSException("File " + lEnterpriseFileName + " is read-only. Unable to update enterprise. EnterpriseRef: " + pEnterpriseDef.getEnterpriseRef());
      // Clean up the cache prior to saving the new file
      cDOMObjectsCache.remove(pEnterpriseDef.getEnterpriseRef() + ";" + EnterpriseDefType.class.getName());
      FileOutputStream lFileOutputStream = null;
      try
      {
        lFileOutputStream = new FileOutputStream(lEnterpriseFile);
        getMarshaller().marshal(pEnterpriseDef,lFileOutputStream);
        lFileOutputStream.flush();
        lFileOutputStream.close();
        lFileOutputStream = null;
        cDOMObjectsCache.put(pEnterpriseDef.getEnterpriseRef() + ";" + EnterpriseDefType.class.getName(),pEnterpriseDef);
      }
      catch(IOException e)
      {
        throw new PSException("Caught exception while writing file : " + lEnterpriseFileName, e);
      }
      finally
      {
        try
        {
          if (lFileOutputStream != null)
            lFileOutputStream.close();
        }
        catch(IOException e)
        {
        }
      }
    }          
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
  }

  /** Updates domain details on storage */
  public static void updateDomain(DomainDefType pDomainDef) throws PSException
  {
    try
    {
      try
      {
        getValidator().validate(pDomainDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("Domain definition validation exception. DomainRef: " + pDomainDef.getDomainRef(), e);
      }
      // DomainRef always consists of three parts - enterprise name . system name . domain name
      StringTokenizer lTokenizer = new StringTokenizer(pDomainDef.getDomainRef(),".",false);
      if (lTokenizer.countTokens() != 3)
        throw new PSException("Invalid DomainRef: " + pDomainDef.getDomainRef());
      String lEnterpriseName = lTokenizer.nextToken();
      String lSystemName = lTokenizer.nextToken();
      String lDomainName = lTokenizer.nextToken();
      String lDomainFileName = cEnterpriseRootDir + File.separator +
                   lEnterpriseName + File.separator +
                   cEnterpriseSystemsSubDir + File.separator +
                   lSystemName + File.separator +
                   cEnterpriseDomainsSubDir + File.separator +
                   lDomainName + "DomainDescriptor.xml";
      File lDomainFile = new File(lDomainFileName);
      if (lDomainFile.exists() == false)
        throw new PSException("File " + lDomainFileName + " does not exist. Unable to update domain. DomainRef: " + pDomainDef.getDomainRef());
      if (lDomainFile.canWrite() == false)
        throw new PSException("File " + lDomainFileName + " is read-only. Unable to update domain. DomainRef: " + pDomainDef.getDomainRef());
      // Clean up the cache prior to saving the new file
      cDOMObjectsCache.remove(pDomainDef.getDomainRef() + ";" + DomainDefType.class.getName());
      FileOutputStream lFileOutputStream = null;
      try
      {
        lFileOutputStream = new FileOutputStream(lDomainFile);
        getMarshaller().marshal(pDomainDef,lFileOutputStream);
        lFileOutputStream.flush();
        lFileOutputStream.close();
        lFileOutputStream = null;
        cDOMObjectsCache.put(pDomainDef.getDomainRef() + ";" + DomainDefType.class.getName(),pDomainDef);
      }
      catch(IOException e)
      {
        throw new PSException("Caught exception while writing file : " + lDomainFileName, e);
      }
      finally
      {
        try
        {
          if (lFileOutputStream != null)
            lFileOutputStream.close();
        }
        catch(IOException e)
        {
        }
      }
    }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
  }
  
  /** Deletes system details on storage */
  public static void deleteSystem(String pSystemRef) throws PSException
  {
    try
    {
      String lSystemDirectoryName = getSystemDirectory(pSystemRef);
      File lSystemDirectory = new File(lSystemDirectoryName);
      if (!lSystemDirectory.exists())
        throw new PSException("Directory " + lSystemDirectoryName + " does not exist. Unable to delete system. SystemRef: " + pSystemRef);
      if (!DirectoryUtils.canDelete(lSystemDirectory))
        throw new PSException("Directory " + lSystemDirectoryName + " is not writeable. Unable to delete system. SystemRef: " + pSystemRef);
      cDOMObjectsCache.remove(pSystemRef + ";" + SystemDefType.class.getName());
      DirectoryUtils.deleteDirectory(lSystemDirectory);
    }
    catch(IOException e)
    {
      throw new PSException("Caught exception while deleting System. SystemRef: " + pSystemRef, e);
    }
  }

    /** Updates system details on storage */
    public static void updateSystem(SystemDefType pSystemDef) throws PSException
    {
      try
      {
      try
      {
        getValidator().validate(pSystemDef);
      }
      catch(ValidationException  e)
      {
        throw new PSContentConstraintViolationException("System definition validation exception. SystemRef: " + pSystemDef.getSystemRef(), e);
      }
          String lSystemDirectoryName = getSystemDirectory(pSystemDef.getSystemRef());
          String lSystemFileName = lSystemDirectoryName + File.separator + "Descriptor.xml";
          File lSystemFile = new File(lSystemFileName);
          if (lSystemFile.exists() == false)
              throw new PSException("File " + lSystemFileName + " does not exist. Unable to update system. SystemRef: " + pSystemDef.getSystemRef());
          if (lSystemFile.canWrite() == false)
              throw new PSException("File " + lSystemFileName + " is read-only. Unable to update system. SystemRef: " + pSystemDef.getSystemRef());
          // Clean up the cache prior to saving the new file
          cDOMObjectsCache.remove(pSystemDef.getSystemRef() + ";" + SystemDefType.class.getName());
          FileOutputStream lFileOutputStream = null;
          try
          {
              lFileOutputStream = new FileOutputStream(lSystemFile);
        getMarshaller().marshal(pSystemDef,lFileOutputStream);
              lFileOutputStream.flush();
              lFileOutputStream.close();
              lFileOutputStream = null;
              cDOMObjectsCache.put(pSystemDef.getSystemRef() + ";" + SystemDefType.class.getName(),pSystemDef);
          }
          catch(IOException e)
          {
              throw new PSException("Caught exception while writing file : " + lSystemFileName, e);
          }
          finally
          {
              try
              {
                  if (lFileOutputStream != null)
                      lFileOutputStream.close();
              }
              catch(IOException e)
              {
              }
          }
      }
    catch(JAXBException  e)
    {
      throw new PSDataSourceOperationInvocationException(e);
    }
    }

  /** Returns Association def or null if none found */
  public static AssociationDefType getAssociation(String pAssociationRef) throws PSException
  {
    // First see if we have this object already
    AssociationDefType lRet = (AssociationDefType)cDOMObjectsCache.get(pAssociationRef + ";" + AssociationDefType.class.getName());
    if (lRet == null)
    {
      // AssociationRef always consists of four parts - enterprise name . system name . domain name . association name
      StringTokenizer lTokenizer = new StringTokenizer(pAssociationRef,".",false);
      if (lTokenizer.countTokens() != 4)
        throw new PSException("Invalid AssociationRef: " + pAssociationRef);
      String lEnterpriseName = lTokenizer.nextToken();
      String lSystemName = lTokenizer.nextToken();
      String lDomainName = lTokenizer.nextToken();
      String lAssociationName = lTokenizer.nextToken();
      DomainDefType lDomainDef = getDomain(lEnterpriseName + "." + lSystemName + "." + lDomainName);
      List lAssociations = lDomainDef.getAssociationDefList().getAssociationDef();
      Iterator lIter = lAssociations.iterator();
      while (lIter.hasNext())
      {
        AssociationDefType lAssociationDef = (AssociationDefType)lIter.next();
        if (lAssociationDef.getAssociationRef().equals(pAssociationRef))
        {
          cDOMObjectsCache.put(pAssociationRef + ";" + AssociationDefType.class.getName(),lRet = lAssociationDef);
          break;
        }
      }
    }
    return lRet;
  }

//    /** Returns Association Role Def or null if none found */
//    public static AssociationRoleDefType getAssociationRole(String pAssociationRoleRef) throws PSException
//    {
//    // First see if we have this object already
//    AssociationRoleDefType lRet = (AssociationRoleDefType)cDOMObjectsCache.get(pAssociationRoleRef + ";" + AssociationRoleDefType.class.getName());
//    if (lRet == null)
//    {
//      // AssociationRoleRef always consists of five parts - enterprise name . system name . domain name . association name . role name
//          StringTokenizer lTokenizer = new StringTokenizer(pAssociationRoleRef,".",false);
//          if (lTokenizer.countTokens() != 5)
//        throw new PSException("Invalid AssociationRoleRef: " + pAssociationRoleRef);
//          String lEnterpriseName = lTokenizer.nextToken();
//          String lSystemName = lTokenizer.nextToken();
//          String lDomainName = lTokenizer.nextToken();
//          String lAssociationName = lTokenizer.nextToken();
//      String lAssociationRoleName = lTokenizer.nextToken();
//      AssociationDefType lAssociationDef = getAssociation(lEnterpriseName + "." + lSystemName + "." + lDomainName + "." + lAssociationName);
//      if (lAssociationDef != null)
//      {
//        // Try role A first
//        AssociationRoleDefType lRoleA = (AssociationRoleDefType)lAssociationDef.getAssociationRoleDef().get(0);
//        AssociationRoleDefType lRoleB = (AssociationRoleDefType)lAssociationDef.getAssociationRoleDef().get(1);
//        if (lRoleA.getName().equals(lAssociationRoleName))
//          lRet = lRoleA;
//        else
//        if (lRoleB.getName().equals(lAssociationRoleName))
//          lRet = lRoleB;
//      }
//      if (lRet != null)  
//              cDOMObjectsCache.put(pAssociationRoleRef + ";" + AssociationRoleDefType.class.getName(),lRet);
//    }
//    return lRet;
//    }

    /** Returns Application def or null if none found */
    public static ApplicationDefType getApplication(String pApplicationRef) throws PSException
    {
        // First see if we have this object already
    ApplicationDefType lRet = (ApplicationDefType)cDOMObjectsCache.get(pApplicationRef + ";" + ApplicationDefType.class.getName());
        if (lRet == null)
        {
            // ApplicationRef always consists of three parts - enterprise name . system name . application name
            StringTokenizer lTokenizer = new StringTokenizer(pApplicationRef,".",false);
            if (lTokenizer.countTokens() != 3)
                throw new PSException("Invalid ApplicationRef: " + pApplicationRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lApplicationName = lTokenizer.nextToken();
            String lApplicationFileName = cEnterpriseRootDir + File.separator +
                                          lEnterpriseName + File.separator +
                                          cEnterpriseSystemsSubDir + File.separator +
                                          lSystemName + File.separator +
                                          cEnterpriseApplicationsSubDir + File.separator +
                                          lApplicationName + File.separator + "Descriptor.xml";

            InputStream lInputStream = null;
            try
            {
                lInputStream = openFileStream(lApplicationFileName);
                if (lInputStream != null)
                {
                    if((lRet = (ApplicationDefType)getUnmarshaller().unmarshal(lInputStream)) != null)
                    {
                        if (!lRet.getApplicationRef().equals(pApplicationRef))
                            throw new PSReadDataIntegrityViolationException("Mismatch between ApplicationRef stored in file and the one implied by its location. ApplicationRef : " + lRet.getApplicationRef() + ", Location : " + lApplicationFileName);
                        cDOMObjectsCache.put(pApplicationRef + ";" + ApplicationDefType.class.getName(),lRet);
                    }
                }
            }
            catch(JAXBException e)
            {
                throw new PSDataSourceOperationInvocationException(e);
            }
            finally
            {
                try
                {
                    if (lInputStream != null)
                        lInputStream.close();
                }
                catch(IOException e)
                {
                }
            }
        }
        return lRet;
    }

    /** All parts found in the application */
    public static String[] getApplicationPartsURLs(String pApplicationRef) throws PSException
    {
        try
        {
            // ApplicationRef always consists of three parts - enterprise name . system name . application name
            StringTokenizer lTokenizer = new StringTokenizer(pApplicationRef,".",false);
            if (lTokenizer.countTokens() != 3)
                throw new PSException("Invalid ApplicationRef: " + pApplicationRef);
            String lEnterpriseName = lTokenizer.nextToken();
            String lSystemName = lTokenizer.nextToken();
            String lApplicationName = lTokenizer.nextToken();
            String lApplicationWWWRoot = cEnterpriseRootDir + File.separator +
                                          lEnterpriseName + File.separator +
                                          cEnterpriseSystemsSubDir + File.separator +
                                          lSystemName + File.separator +
                                          cEnterpriseApplicationsSubDir + File.separator +
                                          lApplicationName + File.separator + "wwwroot";
            int lApplicationWWWRootNameLength = lApplicationWWWRoot.length();

            String[] lAllFileNames = DirectoryUtils.listAllFilesInDirectory(lApplicationWWWRoot);
            // Chop off the root directory part
            for (int i = 0; i < lAllFileNames.length; i++)
                lAllFileNames[i] = lAllFileNames[i].substring(lApplicationWWWRootNameLength);
            return lAllFileNames;
        }
        catch(IOException e)
        {
            throw new PSException("Caught exception while getting application urls.", e);
        }

    }

    private static InputStream openFileStream(String pFilePath)
    {
        File lFile = new File(pFilePath);
        try
        {
            if (lFile.exists() && lFile.isFile() && lFile.canRead())
                return new FileInputStream(lFile);
            return null;
        }
        catch(FileNotFoundException e)
        {
            return null;
        }
    }

    // Helper. Returns path for the metamodel path or null if basic one will do
    private static final String sMetaBossHome = System.getProperty("MetaBoss.Home");
    private static String[] sPublicMetaModelPath = null;
    private static String[] getPublicMetaModelPath() throws PSException
    {
        if (sPublicMetaModelPath == null)
        {
            if (sMetaBossHome == null || sMetaBossHome.length() == 0)
                throw new PSUndefinedSystemPropertyException("MetaBoss.Home");
      sPublicMetaModelPath = new String[] { sMetaBossHome + File.separator + "metalib" };
        }
        return sPublicMetaModelPath;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.