/*
* (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.eo;
import java.io.File;
import java.io.IOException;
import java.text.Collator;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.dm.DMEntity;
import org.openflexo.foundation.dm.DMModel;
import org.openflexo.foundation.dm.DMObject;
import org.openflexo.foundation.dm.DMRepository;
import org.openflexo.foundation.dm.dm.EOModelRegistered;
import org.openflexo.foundation.dm.dm.EOModelUnregistered;
import org.openflexo.foundation.dm.eo.model.EOEntity;
import org.openflexo.foundation.dm.eo.model.EOModel;
import org.openflexo.foundation.dm.eo.model.EOModelGroup;
import org.openflexo.foundation.rm.DuplicateResourceException;
import org.openflexo.foundation.rm.FlexoDMResource;
import org.openflexo.foundation.rm.InvalidFileNameException;
import org.openflexo.foundation.rm.ProjectRestructuration;
import org.openflexo.foundation.utils.FlexoProjectFile;
import org.openflexo.foundation.wkf.dm.WKFAttributeDataModification;
import org.openflexo.toolbox.FileUtils;
/**
* Represents a database implementation for a group of objects stored in a list of DMEOModel Contains a list of DMEOModel
*
* @author sguerin
*
*/
public abstract class DMEORepository extends DMRepository {
static final Logger logger = Logger.getLogger(DMEORepository.class.getPackage().getName());
// ==========================================================================
// ============================= Instance variables
// =========================
// ==========================================================================
private DMEOModelHashtable _DMEOModels;
private Hashtable<EOEntity, DMEOEntity> _entitiesForEOEntity;
private String entitySubPath;
private class DMEOModelHashtable extends Hashtable<String, DMEOModel> {
public DMEOModelHashtable() {
super();
}
public DMEOModelHashtable(Hashtable<String, DMEOModel> ht) {
super(ht);
}
@Override
public Enumeration<String> keys() {
if (isSerializing()) {
// Order keys in this case
Vector<String> orderedKeys = new Vector<String>();
for (Enumeration<String> en = super.keys(); en.hasMoreElements();) {
orderedKeys.add(en.nextElement());
}
Collections.sort(orderedKeys, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Collator.getInstance().compare(o1, o2);
}
});
return orderedKeys.elements();
}
return super.keys();
}
}
// ==========================================================================
// ============================= Constructor
// ================================
// ==========================================================================
/**
* Default constructor
*/
public DMEORepository(DMModel dmModel) {
super(dmModel);
_DMEOModels = new DMEOModelHashtable();
_entitiesForEOEntity = new Hashtable<EOEntity, DMEOEntity>();
}
public Hashtable<String, DMEOModel> getDMEOModels() {
return _DMEOModels;
}
public void setDMEOModels(Hashtable<String, DMEOModel> eoModels) {
// Transtype to DMEntityHashtable
_DMEOModels = new DMEOModelHashtable(eoModels);
needsReordering = true;
setChanged();
}
public void setDMEOModelForKey(DMEOModel eoModel, String eoModelName) {
eoModel.setRepository(this);
_DMEOModels.put(eoModelName, eoModel);
needsReordering = true;
}
public void removeDMEOModelWithKey(String eoModelName) {
_DMEOModels.remove(eoModelName);
needsReordering = true;
setChanged();
}
/**
* Overrides getEmbeddedDMObjects
*
* @see org.openflexo.foundation.dm.DMRepository#getEmbeddedDMObjects()
*/
@Override
public Vector<DMObject> getEmbeddedDMObjects() {
Vector<DMObject> v = super.getEmbeddedDMObjects();
v.addAll(getDMEOModels().values());
return v;
}
public void internallyRegisterDMEOEntity(DMEOEntity dmEOEntity) {
if (dmEOEntity.getEOEntity() != null) {
if (_entitiesForEOEntity.get(dmEOEntity.getEOEntity()) != null) {
if (_entitiesForEOEntity.get(dmEOEntity.getEOEntity()) != dmEOEntity) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Trying to redefine DMEOEntity: operation not allowed !");
}
} else {
// Ignore it !
}
} else {
_entitiesForEOEntity.put(dmEOEntity.getEOEntity(), dmEOEntity);
}
}
}
private void internallyUnregisterDMEOEntity(DMEOEntity dmEOEntity) {
if (dmEOEntity.getEOEntity() != null) {
_entitiesForEOEntity.remove(dmEOEntity.getEOEntity());
}
}
@Override
public void setEntityForKey(DMEntity entity, String entityName) {
if (entity instanceof DMEOEntity) {
DMEOEntity dmEOEntity = (DMEOEntity) entity;
internallyRegisterDMEOEntity(dmEOEntity);
if (dmEOEntity.getDMEOModel() != null) {
dmEOEntity.getDMEOModel().registerEntity(dmEOEntity);
}
}
super.setEntityForKey(entity, entityName);
}
@Override
public void removeEntityWithKey(String entityName, boolean notify) {
DMEntity entity = getDMEntity(entityName);
if (entity != null && entity instanceof DMEOEntity) {
DMEOEntity dmEOEntity = (DMEOEntity) entity;
internallyUnregisterDMEOEntity(dmEOEntity);
if (dmEOEntity.getDMEOModel() != null) {
dmEOEntity.getDMEOModel().unregisterEntity(dmEOEntity, notify);
}
}
super.removeEntityWithKey(entityName, notify);
}
public DMEOEntity getDMEOEntity(EOEntity eoEntity) {
return _entitiesForEOEntity.get(eoEntity);
}
public DMEOModel importEOModelFile(FlexoProjectFile eoModelDir, DMModel dmModel, FlexoDMResource dmRes)
throws InvalidEOModelFileException, EOModelAlreadyRegisteredException, InvalidFileNameException {
DMEOModel newEOModel = null;
try {
newEOModel = DMEOModel.createsNewDMEOModelFromExistingEOModel(dmModel, this, eoModelDir, dmRes);
EOModel model = newEOModel.loadEOModel();
if (model == null) {
if (newEOModel.getEOModelResource() != null) {
getProject().removeResource(newEOModel.getEOModelResource());
}
throw new InvalidEOModelFileException(newEOModel.getEOModelResource());
}
registerEOModel(newEOModel);
return newEOModel;
} catch (DuplicateResourceException e) {
throw new EOModelAlreadyRegisteredException(eoModelDir);
}
}
public DMEOModel importEOModelFile(FlexoProjectFile eoModelDir) throws InvalidEOModelFileException, EOModelAlreadyRegisteredException,
InvalidFileNameException {
return importEOModelFile(eoModelDir, getDMModel(), null);
}
public DMEOModel copyAndImportEOModel(File eoModelFile) throws EOAccessException, InvalidEOModelFileException,
EOModelAlreadyRegisteredException, InvalidFileNameException, UnresovedEntitiesException {
DMEOModel importedDMEOModel = null;
File dataModelDir = ProjectRestructuration.getExpectedDataModelDirectory(getProject().getProjectDirectory());
if (!dataModelDir.equals(eoModelFile.getParentFile())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Copying file " + eoModelFile.getAbsolutePath() + " to " + dataModelDir.getAbsolutePath());
}
File dest = new File(dataModelDir, eoModelFile.getName());
for (DMEOModel model : getDMModel().getAllDMEOModel()) {
if (model.getEOModelFile().getFile().equals(dest)) {
throw new EOModelAlreadyRegisteredException(model.getEOModelFile());
}
}
try {
FileUtils.copyDirToDir(eoModelFile, dataModelDir);
} catch (IOException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not copy file " + eoModelFile.getAbsolutePath() + " to " + dataModelDir.getAbsolutePath());
}
}
}
try {
FlexoProjectFile eoModelDirectory = new FlexoProjectFile(new File(dataModelDir, eoModelFile.getName()), getProject());
importedDMEOModel = importEOModelFile(eoModelDirectory);
importedDMEOModel.updateFromEOModel();
if (importedDMEOModel.getEOModel().getMissingEntities().size() > 0) {
throw new UnresovedEntitiesException(importedDMEOModel.getEOModel().getMissingEntities());
}
} catch (InvalidEOModelFileException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not import EOModel:" + dataModelDir.getName());
}
if (importedDMEOModel != null) {
importedDMEOModel.delete();
}
throw e;
} catch (EOAccessException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not import EOModel:" + dataModelDir.getName());
}
if (importedDMEOModel != null) {
importedDMEOModel.delete();
}
throw e;
} catch (EOModelAlreadyRegisteredException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not import EOModel:" + dataModelDir.getName());
}
if (importedDMEOModel != null) {
importedDMEOModel.delete();
}
throw e;
}
return importedDMEOModel;
}
public DMEOModel createsNewEOModel(File eoModelFile, DMEOAdaptorType adaptor, String username, String passwd, String databaseServerURL,
String plugin, String driver) throws InvalidEOModelFileException, DuplicateResourceException, InvalidFileNameException,
IOException {
File dataModelDir = ProjectRestructuration.getExpectedDataModelDirectory(getProject().getProjectDirectory());
FlexoProjectFile eoModelDirectory = new FlexoProjectFile(new File(dataModelDir, eoModelFile.getName()), getProject());
eoModelDirectory.getFile().mkdirs();
DMEOModel newEOModel;
newEOModel = DMEOModel.createsNewDMEOModelForNewEOModel(getDMModel(), this, eoModelDirectory, adaptor, username, passwd,
databaseServerURL, plugin, driver);
registerEOModel(newEOModel);
return newEOModel;
}
public void registerEOModel(DMEOModel eoModel) {
eoModel.setRepository(this);
if (_DMEOModels.get(eoModel.getName()) == null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Register EOModel " + eoModel.getName());
}
setDMEOModelForKey(eoModel, eoModel.getName());
setChanged();
notifyObservers(new EOModelRegistered(eoModel));
} else if (eoModel != _DMEOModels.get(eoModel.getName())) {
eoModel.setRepository(null);
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Trying to redefine EOModel " + eoModel.getName() + ": operation not allowed !");
}
}
}
public void unregisterEOModel(DMEOModel eoModel) {
removeDMEOModelWithKey(eoModel.getName());
eoModel.setRepository(null);
setChanged();
notifyObservers(new EOModelUnregistered(eoModel));
}
protected void renameEOModel(DMEOModel eoModel, String oldName, String newName) {
if (_DMEOModels.get(oldName + ".eomodeld") == eoModel) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Rename EOModel from " + oldName + ".eomodeld" + " to " + newName + ".eomodeld");
}
removeDMEOModelWithKey(oldName + ".eomodeld");
setDMEOModelForKey(eoModel, newName + ".eomodeld");
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("oldName=" + oldName);
logger.fine("newName=" + newName);
logger.fine("_DMEOModels.get(oldName)=" + _DMEOModels.get(oldName));
logger.fine("eoModel=" + eoModel);
}
logger.warning("Inconsistant data when trying to rename EOModel from " + oldName + " to " + newName);
}
}
public EOModelGroup getModelGroup() {
return getDMModel().getModelGroup();
}
/**
* Return all EOModels declared for this repository, as a Vector of DMEOModels
*
* @return
*/
public Vector<DMEOModel> getOrderedDMEOModels() {
return (Vector<DMEOModel>) getOrderedChildren();
}
@Override
public final void delete() {
delete(false);
}
public void delete(boolean deleteEOModelFiles) {
Vector eoModelsToDelete = new Vector();
eoModelsToDelete.addAll(getDMEOModels().values());
for (Enumeration en = eoModelsToDelete.elements(); en.hasMoreElements();) {
DMEOModel next = (DMEOModel) en.nextElement();
next.delete(deleteEOModelFiles);
}
_DMEOModels.clear();
_DMEOModels = null;
_entitiesForEOEntity.clear();
_entitiesForEOEntity = null;
super.delete();
// Observers are deleted in super implementation
// deleteObservers();
}
// ==========================================================================
// ============================= Sorting stuff
// ==============================
// ==========================================================================
private Vector<DMEOModel> orderedEOModels;
private boolean needsReordering = true;
@Override
public Vector<? extends DMObject> getOrderedChildren() {
if (needsReordering) {
reorderEOModels();
}
return orderedEOModels;
}
private void reorderEOModels() {
if (needsReordering) {
if (orderedEOModels != null) {
orderedEOModels.removeAllElements();
} else {
orderedEOModels = new Vector<DMEOModel>();
}
orderedEOModels.addAll(_DMEOModels.values());
Collections.sort(orderedEOModels, eoModelComparator);
needsReordering = false;
}
}
protected static final EOModelComparator eoModelComparator = new EOModelComparator();
/**
* Used to sort entities according to name alphabetic ordering
*
* @author sguerin
*
*/
protected static class EOModelComparator implements Comparator<DMEOModel> {
/**
* 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(DMEOModel o1, DMEOModel 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 notifyReordering(DMObject cause) {
needsReordering = true;
super.notifyReordering(cause);
}
public String getEntitySubPath() {
if (entitySubPath == null) {
entitySubPath = "src/main/java/EO" + FileUtils.getValidFileName(this.getName());
}
return entitySubPath;
}
public void setEntitySubPath(String entitySubPath) {
String old = this.entitySubPath;
this.entitySubPath = entitySubPath;
setChanged();
notifyObservers(new WKFAttributeDataModification("entitySubPath", old, entitySubPath));
}
public Hashtable<EOEntity, DMEOEntity> getEntitiesForEOEntity() {
return _entitiesForEOEntity;
}
}