/* * (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.sg.implmodel; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import java.util.logging.Logger; import javax.naming.InvalidNameException; import org.openflexo.foundation.rm.DuplicateResourceException; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.foundation.rm.FlexoResource; import org.openflexo.foundation.rm.ImplementationModelResource; import org.openflexo.foundation.rm.SaveResourceException; import org.openflexo.foundation.rm.XMLStorageResourceData; import org.openflexo.foundation.sg.implmodel.enums.TechnologyLayer; import org.openflexo.foundation.sg.implmodel.event.SGObjectAddedToListModification; import org.openflexo.foundation.sg.implmodel.event.SGObjectRemovedFromListModification; import org.openflexo.foundation.sg.implmodel.exception.TechnologyModuleCompatibilityCheckException; import org.openflexo.foundation.xml.ImplementationModelBuilder; import org.openflexo.xmlcode.XMLMapping; public class ImplementationModel extends ImplModelObject implements XMLStorageResourceData { private static final Logger logger = Logger.getLogger(ImplementationModel.class.getPackage().getName()); private ImplementationModelResource _resource; private ImplementationModelDefinition _implModelDefinition; private LinkedHashMap<String, TechnologyModuleImplementation> technologyModules = new LinkedHashMap<String, TechnologyModuleImplementation>(); // <Module // definition // name, // implementation> private boolean isAddingModule = false; /** * Constructor invoked during deserialization * * @param componentDefinition */ public ImplementationModel(ImplementationModelBuilder builder) { this(builder.definition, builder.getProject()); builder.implementationModel = this; initializeDeserialization(builder); } /** * Default constructor for OEShema * * @param shemaDefinition */ public ImplementationModel(ImplementationModelDefinition implModelDefinition, FlexoProject project) { super(project); logger.info("Created new implementation model for project " + project); _implModelDefinition = implModelDefinition; setImplementationModel(this); } public ImplementationModelDefinition getImplementationModelDefinition() { return _implModelDefinition; } @Override public ImplementationModelResource getFlexoResource() { return _resource; } @Override public ImplementationModelResource getFlexoXMLFileResource() { return getFlexoResource(); } @Override @SuppressWarnings("rawtypes") public void setFlexoResource(FlexoResource resource) throws DuplicateResourceException { _resource = (ImplementationModelResource) resource; } @Override public void save() throws SaveResourceException { getFlexoResource().saveResourceData(); } @Override public String getClassNameKey() { return "implementation_model"; } @Override public String getName() { if (getImplementationModelDefinition() != null) { return getImplementationModelDefinition().getName(); } return null; } @Override public void setName(String name) throws DuplicateResourceException, InvalidNameException { if (getImplementationModelDefinition() != null) { getImplementationModelDefinition().setName(name); } } @Override public String getDescription() { if (isSerializing()) { return null; } if (getImplementationModelDefinition() != null) { return getImplementationModelDefinition().getDescription(); } return super.getDescription(); } @Override public void setDescription(String description) { if (getImplementationModelDefinition() != null) { getImplementationModelDefinition().setDescription(description); } super.setDescription(description); } @Override public Map<String, String> getSpecificDescriptions() { if (isSerializing()) { return null; } if (getImplementationModelDefinition() != null) { return getImplementationModelDefinition().getSpecificDescriptions(); } return super.getSpecificDescriptions(); } @Override public boolean getHasSpecificDescriptions() { if (getImplementationModelDefinition() != null) { return getImplementationModelDefinition().getHasSpecificDescriptions(); } return super.getHasSpecificDescriptions(); } @Override public String getFullyQualifiedName() { return getProject().getFullyQualifiedName() + "." + getImplementationModelDefinition().getName(); } @Override public XMLMapping getXMLMapping() { return getProject().getXmlMappings().getImplementationModelMapping(); } @Override public String getInspectorName() { return null; } /** * Add the specified implementation and all its required module in the implementation model. <br> * If there is incompatibility with existing module, an TechnologyModuleCompatibilityCheckException is thrown and no module is added. * * @param technologyModuleImplementation * @throws TechnologyModuleCompatibilityCheckException */ @SuppressWarnings("unchecked") public void addToTechnologyModules(TechnologyModuleImplementation technologyModuleImplementation) throws TechnologyModuleCompatibilityCheckException { if (containsTechnologyModule(technologyModuleImplementation.getTechnologyModuleDefinition())) { return; } // Clone the map to restore it in case of compatibility issue LinkedHashMap<String, TechnologyModuleImplementation> clone = (LinkedHashMap<String, TechnologyModuleImplementation>) technologyModules .clone(); boolean currentIsAddingModule = isAddingModule; isAddingModule = true; try { // Add the required modules (addToTechnologyModules will be called at implementation creation) for (TechnologyModuleDefinition requiredModule : technologyModuleImplementation.getTechnologyModuleDefinition() .getRequiredModules()) { try { requiredModule.createNewImplementation(this); } catch (TechnologyModuleCompatibilityCheckException e) { e.prependMessage("Module '" + requiredModule.getName() + "' is required by module '" + technologyModuleImplementation.getTechnologyModuleDefinition().getName() + "'"); throw e; } } // Add specified module technologyModules.put(technologyModuleImplementation.getTechnologyModuleDefinition().getName(), technologyModuleImplementation); // Checks compatibility checkTechnologyModuleCompatibility(); } catch (TechnologyModuleCompatibilityCheckException e) { technologyModules = clone; throw e; } finally { isAddingModule = currentIsAddingModule; } if (!isAddingModule) { setChanged(); notifyObservers(new SGObjectAddedToListModification("technologyModules", technologyModuleImplementation)); } } public void removeFromTechnologyModules(TechnologyModuleImplementation technologyModuleImplementation) { if (technologyModules.remove(technologyModuleImplementation.getTechnologyModuleDefinition().getName()) != null) { // Remove also all dependent modules for (TechnologyModuleImplementation moduleImplementation : new ArrayList<TechnologyModuleImplementation>( technologyModules.values())) { if (moduleImplementation.getTechnologyModuleDefinition().getAllRequiredModules() .contains(technologyModuleImplementation.getTechnologyModuleDefinition())) { removeFromTechnologyModules(moduleImplementation); } } setChanged(); notifyObservers(new SGObjectRemovedFromListModification("technologyModules", technologyModuleImplementation)); } } /** * Perform all necessary checks to ensure compatibility between available modules. * * @throws TechnologyModuleCompatibilityCheckException * if the check fails */ public void checkTechnologyModuleCompatibility() throws TechnologyModuleCompatibilityCheckException { if (isDeserializing()) { return; // No check while deserializing } // 1. Build a map of TechnologyModuleDefinition by layers. Map<TechnologyLayer, Set<TechnologyModuleDefinition>> layerModuleMap = new HashMap<TechnologyLayer, Set<TechnologyModuleDefinition>>(); for (TechnologyModuleImplementation technologyModuleImplementation : getTechnologyModules()) { Set<TechnologyModuleDefinition> set = layerModuleMap.get(technologyModuleImplementation.getTechnologyModuleDefinition() .getTechnologyLayer()); if (set == null) { set = new HashSet<TechnologyModuleDefinition>(); layerModuleMap.put(technologyModuleImplementation.getTechnologyModuleDefinition().getTechnologyLayer(), set); } set.add(technologyModuleImplementation.getTechnologyModuleDefinition()); } // 2. Checks all technology implementation used. for (TechnologyModuleImplementation implementation : technologyModules.values()) { TechnologyModuleDefinition moduleDefinition = implementation.getTechnologyModuleDefinition(); Set<TechnologyModuleDefinition> possibleIncompatibleModules = moduleDefinition.getIncompatibleModules(); if (moduleDefinition.getTechnologyLayer() != TechnologyLayer.MAIN && moduleDefinition.getTechnologyLayer() != TechnologyLayer.TRANSVERSAL) { possibleIncompatibleModules.addAll(layerModuleMap.get(moduleDefinition.getTechnologyLayer())); } for (TechnologyModuleDefinition incompatibleModule : possibleIncompatibleModules) { if (incompatibleModule != moduleDefinition && !incompatibleModule.getCompatibleModules().contains(moduleDefinition) && !incompatibleModule.getRequiredModules().contains(moduleDefinition) && !moduleDefinition.getCompatibleModules().contains(incompatibleModule) && !moduleDefinition.getRequiredModules().contains(incompatibleModule)) { throw new TechnologyModuleCompatibilityCheckException(moduleDefinition, incompatibleModule); } } } } /* ===================== */ /* == Getter / Setter == */ /* ===================== */ public Vector<TechnologyModuleImplementation> getTechnologyModules() { return new Vector<TechnologyModuleImplementation>(technologyModules.values()); } public void setTechnologyModules(Vector<TechnologyModuleImplementation> technologyModules) { this.technologyModules = new LinkedHashMap<String, TechnologyModuleImplementation>(); for (TechnologyModuleImplementation implementation : technologyModules) { this.technologyModules.put(implementation.getTechnologyModuleDefinition().getName(), implementation); } } public boolean containsTechnologyModule(TechnologyModuleDefinition technologyModuleDefinition) { return technologyModules.containsKey(technologyModuleDefinition.getName()); } /** * Retrieve the TechnologyModuleImplementation associated to this technologyModuleDefinition. * * @param technologyModuleDefinition * @return the retrieved TechnologyModuleImplementation is any, null otherwise. */ public TechnologyModuleImplementation getTechnologyModule(TechnologyModuleDefinition technologyModuleDefinition) { return technologyModules.get(technologyModuleDefinition.getName()); } /** * Retrieve the TechnologyModuleImplementation associated to this technologyModuleDefinitionName. * * @param technologyModuleDefinitionName * @return the retrieved TechnologyModuleImplementation is any, null otherwise. */ public TechnologyModuleImplementation getTechnologyModule(String technologyModuleDefinitionName) { return technologyModules.get(technologyModuleDefinitionName); } /** * Retrieve all technology modules available for the specified layer. * * @param technologyLayer * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getTechnologyModules(TechnologyLayer technologyLayer) { List<TechnologyModuleImplementation> result = new Vector<TechnologyModuleImplementation>(); for (TechnologyModuleImplementation technologyModuleImplementation : getTechnologyModules()) { if (technologyModuleImplementation.getTechnologyModuleDefinition().getTechnologyLayer() == technologyLayer) { result.add(technologyModuleImplementation); } } return result; } /** * Retrieve all technology modules available for the GLOBAL layer. * * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getMainTechnologyModules() { return getTechnologyModules(TechnologyLayer.MAIN); } /** * // * Retrieve all technology modules available for the TRANSVERSAL layer. * * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getTransversalTechnologyModules() { return getTechnologyModules(TechnologyLayer.TRANSVERSAL); } /** * Retrieve all technology modules available for the GUI layer. * * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getGUITechnologyModules() { return getTechnologyModules(TechnologyLayer.GUI); } /** * Retrieve all technology modules available for the BUSINESS LOGIC layer. * * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getBusinessLogicTechnologyModules() { return getTechnologyModules(TechnologyLayer.BUSINESS_LOGIC); } /** * Retrieve all technology modules available for the DAO layer. * * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getDAOTechnologyModules() { return getTechnologyModules(TechnologyLayer.DAO); } /** * Retrieve all technology modules available for the DATABASE layer. * * @return the retrieved technology modules. */ public List<TechnologyModuleImplementation> getDatabaseTechnologyModules() { return getTechnologyModules(TechnologyLayer.DATABASE); } }