/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.foundation.xml; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.ParserConfigurationException; import org.jdom2.JDOMException; import org.openflexo.foundation.cg.GeneratedOutput; import org.openflexo.foundation.dkv.DKVModel; import org.openflexo.foundation.dm.DMModel; import org.openflexo.foundation.ie.IEWOComponent; import org.openflexo.foundation.ie.cl.FlexoComponentLibrary; import org.openflexo.foundation.ie.menu.FlexoNavigationMenu; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.foundation.sg.GeneratedSources; import org.openflexo.foundation.sg.implmodel.ImplementationModel; import org.openflexo.foundation.toc.TOCData; import org.openflexo.foundation.view.View; import org.openflexo.foundation.view.ViewLibrary; import org.openflexo.foundation.wkf.FlexoProcess; import org.openflexo.foundation.wkf.FlexoWorkflow; import org.openflexo.foundation.ws.FlexoWSLibrary; import org.openflexo.toolbox.FileResource; import org.openflexo.toolbox.FlexoVersion; import org.openflexo.xmlcode.AccessorInvocationException; import org.openflexo.xmlcode.InvalidModelException; import org.openflexo.xmlcode.InvalidObjectSpecificationException; import org.openflexo.xmlcode.InvalidXMLDataException; import org.openflexo.xmlcode.StringEncoder; import org.openflexo.xmlcode.XMLDecoder; import org.openflexo.xmlcode.XMLMapping; import org.openflexo.xmlcode.XMLSerializable; import org.xml.sax.SAXException; /** * Utility class allowing to perform efficient access to XML mappings. This class additionnaly handles versions of those mappings * * @author sguerin * */ public class FlexoXMLMappings { protected static final Logger logger = Logger.getLogger(FlexoXMLMappings.class.getPackage().getName()); // private boolean isInitialized = false; private ModelVersions modelVersions = null; public FlexoXMLMappings() { initialize(); } // Public API public XMLMapping getRMMapping() { return getMappingForClass(FlexoProject.class); } public XMLMapping getWKFMapping() { return getMappingForClass(FlexoProcess.class); } public XMLMapping getWorkflowMapping() { return getMappingForClass(FlexoWorkflow.class); } public XMLMapping getIEMapping() { return getMappingForClass(IEWOComponent.class); } public XMLMapping getDMMapping() { return getMappingForClass(DMModel.class); } public XMLMapping getComponentLibraryMapping() { return getMappingForClass(FlexoComponentLibrary.class); } public XMLMapping getShemaLibraryMapping() { return getMappingForClass(ViewLibrary.class); } public XMLMapping getShemaMapping() { return getMappingForClass(View.class); } public XMLMapping getGeneratedCodeMapping() { return getMappingForClass(GeneratedOutput.class); } public XMLMapping getGeneratedSourcesMapping() { return getMappingForClass(GeneratedSources.class); } public XMLMapping getImplementationModelMapping() { return getMappingForClass(ImplementationModel.class); } public XMLMapping getNavigationMenuMapping() { return getMappingForClass(FlexoNavigationMenu.class); } public XMLMapping getTOCMapping() { return getMappingForClass(TOCData.class); } public XMLMapping getWSMapping() { return getMappingForClass(FlexoWSLibrary.class); } /** * Returns all available versions for given class, ordered in ascendant order */ public FlexoVersion[] getAvailableVersionsForClass(Class<?> aClass) { if (modelVersions != null) { ClassModels modelsForClass = modelVersions.classModels.get(aClass.getName()); if (modelsForClass != null) { return modelsForClass.getAvailableVersions(); } } if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find latest model file version for class " + aClass.getName()); } return null; } public XMLMapping getMappingForClass(Class<?> aClass) { return getMappingForClassAndVersion(aClass, getLatestVersionForClass(aClass)); } public XMLMapping getMappingForClassAndVersion(Class<?> aClass, FlexoVersion version) { ClassModelVersion cmv = getClassModelVersion(aClass, version); if (cmv != null) { return cmv.getMapping(); } if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find model file for class " + aClass.getName() + " and version " + version); } return null; } public ClassModels getModelsForClass(Class<?> aClass) { return modelVersions.classModels.get(aClass.getName()); } public ClassModelVersion getClassModelVersion(Class<?> aClass, FlexoVersion version) { if (modelVersions != null) { if (logger.isLoggable(Level.FINE)) { logger.finest("Searching ClassModelFlexoVersion for class " + aClass.getName()); } ClassModels modelsForClass = getModelsForClass(aClass); if (modelsForClass != null) { if (logger.isLoggable(Level.FINE)) { logger.finest("Searching ClassModelFlexoVersion for version " + version); } ClassModelVersion foundFlexoVersion = modelsForClass.classModelVersions.get(version); if (foundFlexoVersion != null) { return foundFlexoVersion; } } } if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find model file for class " + aClass.getName() + " and version " + version); } return null; } public FlexoVersion getLatestVersionForClass(Class<?> aClass) { if (modelVersions != null && aClass != null) { ClassModels modelsForClass = modelVersions.classModels.get(aClass.getName()); if (modelsForClass != null) { return modelsForClass.latestVersion; } } return null; } public FlexoVersion getVersionForClassAndRelease(Class<?> aClass, FlexoVersion releaseVersion) { if (modelVersions != null && aClass != null) { ReleaseModels modelsForRelease = modelVersions.releaseModels.get(releaseVersion); if (modelsForRelease != null) { if (modelsForRelease.classModels.get(aClass.getName()) != null) { return modelsForRelease.classModels.get(aClass.getName()).version; } } } return null; } private static final Vector<FlexoVersion> _releaseVersions = new Vector<FlexoVersion>(); public static Vector<FlexoVersion> getReleaseVersions() { if (_releaseVersions.size() == 0) { for (ReleaseModels rm : new FlexoXMLMappings().modelVersions.releaseModels.values()) { _releaseVersions.add(rm.identifier); } Collections.sort(_releaseVersions, FlexoVersion.comparator); } return _releaseVersions; } public static final FlexoVersion latestRelease() { return getReleaseVersions().lastElement(); } private static XMLMapping getVersionningModel() { // File flexoFoundationDirectory = getFlexoFoundationDirectory(); // File versionningModelFile = new File (flexoFoundationDirectory, // "Models/FlexoVersionningModel.xml"); File versionningModelFile = new FileResource("Models/VersionningModel.xml"); try { return new XMLMapping(versionningModelFile); } catch (InvalidModelException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (IOException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (SAXException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (ParserConfigurationException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } return null; } public void initialize() { // We use here a dedicated and resetted String Converter // Fix a bug where relative path converter overrided File converter, and causing big issues StringEncoder stringEncoder = new StringEncoder(); stringEncoder._addConverter(FlexoVersion.converter); // Register all declared string converters // FlexoObject.initialize(true); // The next line ensure that the FlexoVersion converter is well registered by XMLCoDe // FlexoVersion registerMyConverter = new FlexoVersion("1.0"); // registerMyConverter.toString(); // File flexoFoundationDirectory = getFlexoFoundationDirectory(); // File modelFlexoVersionFile = new File (flexoFoundationDirectory, // "Models/ModelFlexoVersions.xml"); File modelFlexoVersionFile = new FileResource("Models/ModelVersions.xml"); try { modelVersions = (ModelVersions) XMLDecoder.decodeObjectWithMappingAndStringEncoder(new FileInputStream(modelFlexoVersionFile), getVersionningModel(), stringEncoder); Iterator<ClassModels> i = modelVersions.classModels.values().iterator(); while (i.hasNext()) { ClassModels cm = i.next(); if (cm.getAvailableVersions().length == 0) { if (logger.isLoggable(Level.WARNING)) { logger.warning("There are no available versions for " + cm.name); } continue; } FlexoVersion biggest = cm.getAvailableVersions()[0]; for (int j = 0; j < cm.availableFlexoVersions.length; j++) { FlexoVersion v = cm.availableFlexoVersions[j]; if (v.isGreaterThan(biggest)) { biggest = v; } } if (!cm.latestVersion.equals(biggest)) { if (logger.isLoggable(Level.WARNING)) { logger.warning("The latest version is " + cm.latestVersion + " but the greatest version is " + biggest + " for class model named " + cm.name); } } } } catch (InvalidXMLDataException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (InvalidObjectSpecificationException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (AccessorInvocationException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (FileNotFoundException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (JDOMException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); } e.printStackTrace(); } catch (InvalidModelException e) { // Warns about the exception logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); e.printStackTrace(); } catch (IOException e) { // Warns about the exception logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details."); e.printStackTrace(); } if (logger.isLoggable(Level.FINE)) { for (ReleaseModels release : modelVersions.releaseModels.values()) { logger.fine("Release " + release.identifier); for (ReleaseClassModel cm : release.classModels.values()) { logger.fine("Class " + cm.name + " version: " + cm.version); } } } } public static class ModelVersions implements XMLSerializable { /** * Hashtable where are stored ClassModels objects related to key ClassModels.className */ public Hashtable<String, ClassModels> classModels = new Hashtable<String, ClassModels>(); /** * Hashtable where are stored ClassModels objects related to key ReleaseModels.identifier */ public Hashtable<FlexoVersion, ReleaseModels> releaseModels = new Hashtable<FlexoVersion, ReleaseModels>(); } public static class ReleaseModels implements XMLSerializable { public FlexoVersion identifier; /** * Hashtable where are stored ReleaseClassModel objects related to key ReleaseClassModel.name */ public Hashtable<String, ReleaseClassModel> classModels = new Hashtable<String, ReleaseClassModel>(); } public static class ReleaseClassModel implements XMLSerializable { public String name; public FlexoVersion version; } public static class ClassModels implements XMLSerializable { public String name; public FlexoVersion latestVersion; protected FlexoVersion[] availableFlexoVersions; /** * Hashtable where are stored ClassModelFlexoVersion objects related to key ClassModelFlexoVersion.id */ public Hashtable<String, ClassModelVersion> classModelVersions = new Hashtable<String, ClassModelVersion>(); /** * Return all available versions, ordered in ascendant order * * @return */ public FlexoVersion[] getAvailableVersions() { if (availableFlexoVersions == null) { Vector<FlexoVersion> availableFlexoVersionsVector = new Vector<FlexoVersion>(); for (Enumeration<ClassModelVersion> e = classModelVersions.elements(); e.hasMoreElements();) { ClassModelVersion next = e.nextElement(); availableFlexoVersionsVector.add(next.version); } Collections.sort(availableFlexoVersionsVector, FlexoVersion.comparator); availableFlexoVersions = new FlexoVersion[availableFlexoVersionsVector.size()]; for (int i = 0; i < availableFlexoVersionsVector.size(); i++) { availableFlexoVersions[i] = availableFlexoVersionsVector.elementAt(i); } } return availableFlexoVersions; } } public static class ClassModelVersion implements XMLSerializable { public FlexoVersion version; public File modelFile; public boolean needsManualConversion = false; public FlexoVersion toVersion = null; private XMLMapping mapping = null; protected File getModelFile() { // return new // File(getFlexoFoundationDirectory(),"Models"+File.separator+modelFile.getPath()); return new FileResource("Models/" + modelFile.getPath()); } @Override public String toString() { return "ClassModelVersion: file " + modelFile + " version " + version; } public XMLMapping getMapping() { if (mapping == null) { if (getModelFile().exists() && !getModelFile().isDirectory()) { try { mapping = new XMLMapping(getModelFile()); } catch (InvalidModelException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Model version " + version + ", exception raised: " + e.getClass().getName() + ". See console for details. (File is " + getModelFile().getAbsolutePath() + ")"); } e.printStackTrace(); } catch (IOException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.(File is " + getModelFile().getAbsolutePath() + ")\""); } e.printStackTrace(); } catch (SAXException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.(File is " + getModelFile().getAbsolutePath() + ")\""); } e.printStackTrace(); } catch (ParserConfigurationException e) { // Warns about the exception if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.(File is " + getModelFile().getAbsolutePath() + ")\""); } e.printStackTrace(); } } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Model file " + getModelFile().getAbsolutePath() + " doesn't exist or is not a File"); } } } return mapping; } } /** * @return */ public XMLMapping getDKVMapping() { return getMappingForClass(DKVModel.class); } private static final ClassModelVersion rmTSModelVersion = new ClassModelVersion() { @Override protected File getModelFile() { return new FileResource("Models/RMModel/RMModel_TS.xml"); } }; public static XMLMapping getRMTSMapping() { return rmTSModelVersion.getMapping(); } public static ClassModelVersion getRMTSModelVersion() { return rmTSModelVersion; } }