/*
* (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.StringTokenizer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.dm.dm.EntityDeleted;
import org.openflexo.foundation.dm.dm.EntityRegistered;
import org.openflexo.foundation.dm.dm.EntityUnregistered;
import org.openflexo.foundation.xml.FlexoDMBuilder;
import org.openflexo.localization.FlexoLocalization;
/**
* Please comment this class
*
* @author sguerin
*
*/
public class DMPackage extends DMObject {
static final Logger logger = Logger.getLogger(DMPackage.class.getPackage().getName());
public static final String DEFAULT_PACKAGE_NAME = "default_package";
// ==========================================================================
// ============================= Instance variables
// =========================
// ==========================================================================
private String name;
private DMRepository repository;
// List of all entities declared in this package (hashtable of DMEntity)
private Hashtable<String, DMEntity> entities;
// ==========================================================================
// ============================= Constructor
// ================================
// ==========================================================================
/**
* Constructor used during deserialization
*/
public DMPackage(FlexoDMBuilder builder) {
this(builder.dmModel);
initializeDeserialization(builder);
}
/**
* Default constructor
*/
public DMPackage(DMModel dmModel) {
super(dmModel);
entities = new Hashtable<String, DMEntity>();
}
/**
* Constructor used for dynamic creation
*/
public DMPackage(DMModel dmModel, DMRepository repository, String packageName) {
this(dmModel);
this.name = packageName;
this.repository = repository;
}
@Override
public String getFullyQualifiedName() {
return name;
}
/**
* 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 (getRepository() == null || getRepository().isReadOnly()) {
return Inspectors.DM.DM_RO_PACKAGE_INSPECTOR;
} else {
return Inspectors.DM.DM_PACKAGE_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 String getLocalizedName() {
if (getName().equals(DEFAULT_PACKAGE_NAME)) {
return FlexoLocalization.localizedForKey(getName());
}
return getName();
}
@Override
public void setName(String name) {
this.name = name;
setChanged();
if (getRepository() != null) {
getRepository().notifyReordering(this);
}
}
/**
* Overrides isNameValid
*
* @see org.openflexo.foundation.dm.DMObject#isNameValid()
*/
@Override
public boolean isNameValid() {
return true;
}
@Override
public boolean isDeletable() {
for (DMEntity entity : getEntities()) {
if (!entity.isDeletable()) {
return false;
}
}
return getRepository() != null && !getRepository().isReadOnly();
}
public DMRepository getRepository() {
return repository;
}
public void setRepository(DMRepository repository) {
this.repository = repository;
setChanged();
}
/**
* Return all the entities contained in this package, as a Vector of DMEntity
*
* @return a Vector of DMEntity
*/
public Vector<DMEntity> getEntities() {
return getOrderedChildren();
}
public void registerEntity(DMEntity entity) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Register Entity " + entity.getFullyQualifiedName());
}
if (entities.get(entity.getFullyQualifiedName()) == null) {
entities.put(entity.getFullyQualifiedName(), entity);
entity.addObserver(this);
needsReordering = true;
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 void unregisterEntity(DMEntity entity) {
unregisterEntity(entity, true);
}
public void unregisterEntity(DMEntity entity, boolean notify) {
entities.remove(entity.getFullyQualifiedName());
entity.deleteObserver(this);
needsReordering = true;
if (notify) {
setChanged();
notifyObservers(new EntityUnregistered(entity));
}
/*if (entities.size() == 0) {
getRepository().deletePackage(this);
}*/
}
@Override
public void delete() {
Vector<DMEntity> entitiesToDelete = new Vector<DMEntity>();
entitiesToDelete.addAll(getEntities());
for (Enumeration en = entitiesToDelete.elements(); en.hasMoreElements();) {
DMEntity next = (DMEntity) en.nextElement();
next.delete();
}
if (getRepository() != null) {
getRepository().deletePackage(this);
}
name = null;
repository = null;
entities.clear();
entities = null;
super.delete();
deleteObservers();
}
public String getRelativePath() {
if (getRepository() == null) {
return "";
}
if (this == getRepository().getDefaultPackage()) {
return "";
}
StringBuffer sb = new StringBuffer();
StringTokenizer st = new StringTokenizer(getName(), ".");
boolean isFirst = true;
while (st.hasMoreTokens()) {
sb.append((isFirst ? "" : "/") + st.nextToken());
isFirst = false;
}
return sb.toString();
}
public boolean isDefaultPackage() {
return getName().equals(DMPackage.DEFAULT_PACKAGE_NAME);
// return (getRepository().packages.get(DMPackage.DEFAULT_PACKAGE_NAME) == this);
}
// ==========================================================================
// ============================= Sorting stuff
// ==============================
// ==========================================================================
private Vector<DMEntity> orderedEntities;
private boolean needsReordering = true;
@Override
public synchronized Vector<DMEntity> getOrderedChildren() {
if (needsReordering) {
reorderEntities();
}
return orderedEntities;
}
private synchronized void reorderEntities() {
if (needsReordering) {
if (orderedEntities != null) {
orderedEntities.removeAllElements();
} else {
orderedEntities = new Vector<DMEntity>();
}
orderedEntities.addAll(entities.values());
Collections.sort(orderedEntities, entityComparator);
needsReordering = false;
}
}
protected static final EntityComparator entityComparator = new EntityComparator();
/**
* Used to sort entities according to name alphabetic ordering
*
* @author sguerin
*
*/
protected static class EntityComparator implements Comparator<DMEntity> {
/**
* 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(DMEntity o1, DMEntity o2) {
String s1 = o1.getName();
String s2 = o2.getName();
if (s1 != null && s2 != null) {
return Collator.getInstance().compare(s1, s2);
} else {
return 0;
}
}
}
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
if (dataModification instanceof EntityDeleted) {
unregisterEntity(((EntityDeleted) dataModification).getEntity());
}
super.update(observable, dataModification);
}
@Override
public DMRepository getParent() {
return repository;
}
@Override
public void notifyReordering(DMObject cause) {
needsReordering = true;
super.notifyReordering(cause);
}
/**
* Overrides getClassNameKey
*
* @see org.openflexo.foundation.FlexoModelObject#getClassNameKey()
*/
@Override
public String getClassNameKey() {
return "dm_package";
}
public String getJavaStringRepresentation() {
if (isDefaultPackage()) {
return "";
}
return getName();
}
}