/* * (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.dm; import java.text.Collator; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.Hashtable; import java.util.Map; import java.util.TreeMap; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.foundation.Inspectors; import org.openflexo.foundation.NameChanged; import org.openflexo.foundation.dm.dm.EntityRegistered; import org.openflexo.foundation.dm.dm.EntityUnregistered; import org.openflexo.foundation.dm.dm.PackageCreated; import org.openflexo.foundation.dm.dm.PackageDeleted; /** * Represents logical group of DMEntity sharing the same implementation * * @author sguerin * */ public abstract class DMRepository extends DMObject { private static final Logger logger = Logger.getLogger(DMRepository.class.getPackage().getName()); private String name; // List of all entities declared in this repository (hashtable of DMEntity) protected Map<String, DMEntity> entities; // List of all packages declared in this repository (hashtable of DMPackage) protected Hashtable<String, DMPackage> packages; // ========================================================================== // ============================= Constructor // ================================ // ========================================================================== /** * Default constructor */ public DMRepository(DMModel dmModel) { super(dmModel); entities = new TreeMap<String, DMEntity>(); packages = new Hashtable<String, DMPackage>(); } @Override public String getFullyQualifiedName() { return getDMModel().getFullyQualifiedName() + "." + name; } public abstract boolean isReadOnly(); public abstract int getOrder(); /** * Return String uniquely identifying inspector template which must be applied when trying to inspect this object * * @return a String value */ @Override public String getInspectorName() { if (isReadOnly()) { return Inspectors.DM.DM_RO_REPOSITORY_INSPECTOR; } else { return Inspectors.DM.DM_REPOSITORY_INSPECTOR; } } /** * Return a Vector of embedded DMObjects at this level. * * @return a Vector of embedded DMPackage instances */ @Override public Vector<DMObject> getEmbeddedDMObjects() { Vector<DMObject> returned = new Vector<DMObject>(); returned.addAll(getOrderedChildren()); return returned; } @Override public String getName() { return name; } @Override public void setName(String newName) { String oldName = name; name = newName; setChanged(); notifyObservers(new NameChanged(oldName, newName)); if (getRepositoryFolder() != null) { getRepositoryFolder().notifyReordering(this); } } /** * Overrides isNameValid * * @see org.openflexo.foundation.dm.DMObject#isNameValid() */ @Override public boolean isNameValid() { return true; } @Override public boolean isDeletable() { return !isReadOnly(); } public boolean isUpdatable() { return false; } public abstract DMRepositoryFolder getRepositoryFolder(); public Hashtable<String, DMPackage> getPackages() { return packages; } public void setPackages(Hashtable<String, DMPackage> packages) { this.packages = packages; setChanged(); } public DMPackage packageForEntity(DMEntity entity) { String packageName = entity.getEntityPackageName(); if (packageName == null) { return getDefaultPackage(); } else { return packageWithName(packageName); } } public DMPackage getDefaultPackage() { /* * DMPackage defaultPackage = (DMPackage)packages.get("default"); if (defaultPackage == null) { defaultPackage = new * DMPackage(getDMModel(),this,"default_package"); packages.put("default",defaultPackage); } return defaultPackage; */ return packageWithName(DMPackage.DEFAULT_PACKAGE_NAME); } public DMPackage getPackageWithName(String name) { return packageWithName(name); } public DMPackage packageWithName(String aPackageName) { if (packages.get(aPackageName) == null) { createPackage(aPackageName, false); } return packages.get(aPackageName); } public DMPackage createPackage(String aPackageName) { return createPackage(aPackageName, true); } public DMPackage createPackage(String aPackageName, boolean notify) { // logger.info("Create package "+aPackageName+" for "+this); DMPackage returned = new DMPackage(getDMModel(), this, aPackageName); packages.put(aPackageName, returned); needsReordering = true; if (notify) { setChanged(); notifyObservers(new PackageCreated(returned)); } return returned; } public void deletePackage(DMPackage aPackage) { packages.remove(aPackage.getName()); needsReordering = true; setChanged(); notifyObservers(new PackageDeleted(aPackage)); } public Map<String, DMEntity> getEntities() { return entities; } public void setEntities(Map<String, DMEntity> someEntities) { // Transtype to DMEntityHashtable entities = new TreeMap<String, DMEntity>(someEntities); needsReordering = true; setChanged(); } public void setEntityForKey(DMEntity entity, String entityName) { entity.setRepository(this); entities.put(entityName, entity); getDMModel().registerEntity(entity); packageForEntity(entity).registerEntity(entity); needsReordering = true; setChanged(); } public void removeEntityWithKey(String entityName) { removeEntityWithKey(entityName, true); } public void removeEntityWithKey(String entityName, boolean notify) { entities.remove(entityName); getDMModel().unregisterEntity(entityName); needsReordering = true; if (notify) { setChanged(); } } public void registerEntity(DMEntity entity) { if (entity.getEntityClassName() == null || entity.getEntityClassName().trim().equals("")) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Registering entity " + entity.getFullyQualifiedName() + ": className seems to be not correctely set. Doing it anyway."); } } entity.setRepository(this); if (logger.isLoggable(Level.FINE)) { logger.fine("Register Entity " + entity.getFullyQualifiedName()); } if (entities.get(entity.getFullyQualifiedName()) == null) { setEntityForKey(entity, entity.getFullyQualifiedName()); setChanged(); notifyObservers(new EntityRegistered(entity)); } else if (entity != entities.get(entity.getFullyQualifiedName())) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Trying to redefine entity " + entity.getFullyQualifiedName() + ": operation not allowed !"); } } } public final void unregisterEntity(DMEntity entity) {// GPO: This method is final. If you want to override it, override the 2-args // method unregisterEntity(entity, true); } /** * Unregisters the given <code>entity</code> from this repository and from its package. A notification will be thrown if * <code>notify</code> is true. The purpose of this flag is to avoid notifications for temporary states: if you plan on registering this * entity back in this same repository, then the unregister call can be invoked with false (the registration will notify the observers). * * @param entity * @param notify */ public void unregisterEntity(DMEntity entity, boolean notify) { entity.setRepository(null, notify); removeEntityWithKey(entity.getFullyQualifiedName(), notify); packageForEntity(entity).unregisterEntity(entity, notify); if (notify) { setChanged(); notifyObservers(new EntityUnregistered(entity)); } } public DMEntity getDMEntity(String packageName, String className) { return getEntities().get(packageName + "." + className); } public DMEntity getDMEntity(DMPackage aPackage, String className) { return getDMEntity(aPackage.getName() + "." + className); } public DMEntity getDMEntity(String fullQualifiedName) { return getEntities().get(fullQualifiedName); } public String getStringRepresentation() { String returned = "DMRepository\n"; for (DMEntity entity : entities.values()) { returned += entity.getStringRepresentation(); } return returned; } /** * Delete this repository Take care because all observers are delete here !!! * * Overrides @see org.openflexo.foundation.DeletableObject#delete() * * @see org.openflexo.foundation.DeletableObject#delete() */ @Override public void delete() { Vector<DMObject> entitiesToDelete = new Vector<DMObject>(); entitiesToDelete.addAll(getEntities().values()); for (Enumeration en = entitiesToDelete.elements(); en.hasMoreElements();) { DMEntity next = (DMEntity) en.nextElement(); next.delete(); } Vector<DMObject> packagesToDelete = new Vector<DMObject>(); packagesToDelete.addAll(getPackages().values()); for (Enumeration en = packagesToDelete.elements(); en.hasMoreElements();) { DMPackage next = (DMPackage) en.nextElement(); next.delete(); } getDMModel().unregisterRepository(this); needsReordering = false; name = null; entities.clear(); entities = null; packages.clear(); packages = null; super.delete(); deleteObservers(); } public boolean hasDiagrams() { for (ERDiagram diagram : getDMModel().getDiagrams()) { if (diagram.getRepository() == this) { return true; } } return false; } // ========================================================================== // ============================= Sorting stuff // ============================== // ========================================================================== private Vector<DMPackage> orderedPackages; private boolean needsReordering = true; @Override public synchronized Vector<? extends DMObject> getOrderedChildren() { if (needsReordering) { reorderPackages(); } return orderedPackages; } private synchronized void reorderPackages() { if (needsReordering) { if (orderedPackages != null) { orderedPackages.removeAllElements(); } else { orderedPackages = new Vector<DMPackage>(); } orderedPackages.addAll(packages.values()); Collections.sort(orderedPackages, packageComparator); needsReordering = false; } } protected static final PackageComparator packageComparator = new PackageComparator(); /** * Used to sort entities according to name alphabetic ordering * * @author sguerin * */ static class PackageComparator implements Comparator<DMPackage> { /** * Implements * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(DMPackage o1, DMPackage o2) { if (o1.isDefaultPackage()) { return -1; } if (o2.isDefaultPackage()) { return 1; } String s1 = o1.getName(); String s2 = o2.getName(); if (s1 != null && s2 != null) { return Collator.getInstance().compare(s1, s2); } else { return 0; } } } @Override public DMRepositoryFolder getParent() { return getRepositoryFolder(); // getDMModel(); } @Override public void notifyReordering(DMObject cause) { needsReordering = true; super.notifyReordering(cause); } public void changePackage(DMEntity entity, String oldFullyQualifiedName, String newFullyQualifiedName) { entities.remove(oldFullyQualifiedName); entities.put(newFullyQualifiedName, entity); } }