/*
* (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.tm.hibernate.impl;
import java.util.Collections;
import java.util.Vector;
import javax.naming.InvalidNameException;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.FlexoObserver;
import org.openflexo.foundation.NameChanged;
import org.openflexo.foundation.rm.DuplicateResourceException;
import org.openflexo.foundation.sg.implmodel.ImplementationModel;
import org.openflexo.foundation.sg.implmodel.TechnologyModelObject;
import org.openflexo.foundation.sg.implmodel.TechnologyModuleImplementation;
import org.openflexo.foundation.sg.implmodel.event.SGAttributeModification;
import org.openflexo.foundation.sg.implmodel.event.SGObjectAddedToListModification;
import org.openflexo.foundation.sg.implmodel.event.SGObjectDeletedModification;
import org.openflexo.foundation.sg.implmodel.event.SGObjectRemovedFromListModification;
import org.openflexo.foundation.xml.ImplementationModelBuilder;
import org.openflexo.toolbox.JavaUtils;
/**
* This class defines an entity in the context of an Hibernate implementation.
*
* @author Emmanuel Koch, Blue Pimento Services SPRL
*/
public class HibernateEntity extends TechnologyModelObject implements FlexoObserver {
public static final String CLASS_NAME_KEY = "hibernate_entity";
protected HibernateModel hibernateModel;
/**
* Returns the name of the table that will be used to store this entity in the storage system. If <code>null</code>, the name define the
* table name.
*/
protected String tableName;
/** Indicates if an additional column "Version" must be added to implements optimistic locking. */
protected boolean optimisticLocking;
/** This is the parent entity, when it extends another one. The inverse relation is given by {@link #children}. */
protected HibernateEntity father;
/** This is the sub-entities, extending this one. The inverse relation is given by {@link #father}. */
protected Vector<HibernateEntity> children = new Vector<HibernateEntity>();
/** The attributes of this entity. */
protected Vector<HibernateAttribute> attributes = new Vector<HibernateAttribute>();
/** The relationships of this entity. */
protected Vector<HibernateRelationship> relationships = new Vector<HibernateRelationship>();
// ================ //
// = Constructors = //
// ================ //
/**
* Build a new Hibernate entity for the specified implementation model builder.<br/>
* This constructor is namely invoked during unserialization.
*
* @param builder
* the builder that will create this entity
*/
public HibernateEntity(ImplementationModelBuilder builder) {
this(builder.implementationModel);
initializeDeserialization(builder);
}
/**
* Build a new Hibernate entity for the specified implementation model.
*
* @param implementationModel
* the implementation model where to create this Hibernate entity
*/
public HibernateEntity(ImplementationModel implementationModel) {
super(implementationModel);
}
// =========== //
// = Methods = //
// =========== //
/**
* @Override
*/
@Override
public String getClassNameKey() {
return CLASS_NAME_KEY;
}
/**
* {@inheritDoc}
*/
@Override
public boolean getHasInspector() {
return true;
}
/**
* @Override
*/
@Override
public String getFullyQualifiedName() {
return getHibernateModel().getFullyQualifiedName() + "." + getName();
}
/* ===================== */
/* ====== Actions ====== */
/* ===================== */
/**
* {@inheritDoc}
*/
@Override
public void delete() {
for (HibernateRelationship hibernateRelationship : new Vector<HibernateRelationship>(getRelationships())) {
hibernateRelationship.delete();
}
for (HibernateAttribute hibernateAttribute : new Vector<HibernateAttribute>(getAttributes())) {
hibernateAttribute.delete();
}
for (HibernateEntity hibernateEntity : new Vector<HibernateEntity>(getChildren())) {
hibernateEntity.delete();
}
if (getFather() != null) {
getFather().removeFromChildren(this);
}
if (getHibernateModel() != null) {
getHibernateModel().removeFromEntities(this);
}
setChanged();
notifyObservers(new SGObjectDeletedModification());
super.delete();
deleteObservers();
}
/**
* Retrieve all entities allowed as parent for this entity
*
* @return the retrieved entities
*/
public Vector<HibernateEntity> getEntitiesAllowedAsParent() {
Vector<HibernateEntity> result = new Vector<HibernateEntity>();
for (HibernateEntity entity : getHibernateModel().getEntities()) {
if (entity != this && entity.getFather() == null) {
result.add(entity);
}
}
return result;
}
/**
* Sort attributes stored in this entity by their name.
*/
public void sortAttributes() {
Collections.sort(this.attributes, new FlexoModelObject.FlexoNameComparator<FlexoModelObject>());
}
/**
* Sort relationships stored in this entity by their name.
*/
public void sortRelationships() {
Collections.sort(this.relationships, new FlexoModelObject.FlexoNameComparator<FlexoModelObject>());
}
/**
* Update the table name based on the entity name
*/
public void updateTableName() {
if (!isDeserializing && getHibernateModel() != null) {
setTableName(getHibernateModel().getHibernateImplementation().getDbObjectName(getName()));
}
}
/* ============== */
/* == Observer == */
/* ============== */
/**
* {@inheritDoc}
*/
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
if (dataModification instanceof NameChanged) {
if (observable instanceof HibernateAttribute) {
sortAttributes();
}
if (observable instanceof HibernateRelationship) {
sortRelationships();
}
}
}
/* ===================== */
/* == Getter / Setter == */
/* ===================== */
/**
* {@inheritDoc}
*/
@Override
public void setName(String name) throws DuplicateResourceException, InvalidNameException {
name = JavaUtils.getClassName(name);
if (requireChange(getName(), name)) {
super.setName(name);
updateTableName();
}
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
if (requireChange(this.tableName, tableName)) {
String oldValue = this.tableName;
this.tableName = tableName;
setChanged();
notifyObservers(new SGAttributeModification("tableName", oldValue, tableName));
}
}
public boolean getOptimisticLocking() {
return optimisticLocking;
}
public void setOptimisticLocking(boolean optimisticLocking) {
if (requireChange(this.optimisticLocking, optimisticLocking)) {
Object oldValue = this.optimisticLocking;
this.optimisticLocking = optimisticLocking;
setChanged();
notifyObservers(new SGAttributeModification("optimisticLocking", oldValue, optimisticLocking));
}
}
public HibernateEntity getFather() {
return father;
}
public void setFather(HibernateEntity father) {
if (requireChange(this.father, father)) {
Object oldValue = this.father;
this.father = father;
setChanged();
notifyObservers(new SGAttributeModification("father", oldValue, father));
}
}
/**
* Return the attributes stored in this entity. Attributes are sorted by name.
*
* @return sorted attributes stored in this entity.
*/
public Vector<HibernateAttribute> getAttributes() {
return attributes;
}
public void setAttributes(Vector<HibernateAttribute> attributes) {
if (requireChange(this.attributes, attributes)) {
Vector<HibernateAttribute> oldValue = this.attributes;
for (HibernateAttribute attribute : oldValue) {
attribute.deleteObserver(this);
}
this.attributes = attributes;
for (HibernateAttribute attribute : attributes) {
attribute.addObserver(this);
}
sortAttributes();
setChanged();
notifyObservers(new SGAttributeModification("attributes", oldValue, attributes));
}
}
public void addToAttributes(HibernateAttribute attribute) {
attribute.setHibernateEntity(this);
attributes.add(attribute);
attribute.addObserver(this);
sortAttributes();
setChanged();
notifyObservers(new SGObjectAddedToListModification("attributes", attribute));
}
public void removeFromAttributes(HibernateAttribute attribute) {
if (attributes.remove(attribute)) {
attribute.deleteObserver(this);
setChanged();
notifyObservers(new SGObjectRemovedFromListModification("attributes", attribute));
}
}
/**
* Return the relationships stored in this entity. Relationships are sorted by name.
*
* @return sorted relationships stored in this entity.
*/
public Vector<HibernateRelationship> getRelationships() {
return relationships;
}
public void setRelationships(Vector<HibernateRelationship> relationships) {
if (requireChange(this.relationships, relationships)) {
Vector<HibernateRelationship> oldValue = this.relationships;
for (HibernateRelationship relationship : oldValue) {
relationship.deleteObserver(this);
}
this.relationships = relationships;
for (HibernateRelationship relationship : relationships) {
relationship.addObserver(this);
}
sortRelationships();
setChanged();
notifyObservers(new SGAttributeModification("relationships", oldValue, relationships));
}
}
public void addToRelationships(HibernateRelationship relationship) {
relationship.setHibernateEntity(this);
relationships.add(relationship);
relationship.addObserver(this);
sortRelationships();
setChanged();
notifyObservers(new SGObjectAddedToListModification("relationships", relationship));
}
public void removeFromRelationships(HibernateRelationship relationship) {
if (relationships.remove(relationship)) {
relationship.deleteObserver(this);
setChanged();
notifyObservers(new SGObjectRemovedFromListModification("relationships", relationship));
}
}
public Vector<HibernateEntity> getChildren() {
return children;
}
public void setChildren(Vector<HibernateEntity> children) {
if (requireChange(this.children, children)) {
Object oldValue = this.children;
this.children = children;
setChanged();
notifyObservers(new SGAttributeModification("children", oldValue, children));
}
}
public void addToChildren(HibernateEntity child) {
children.add(child);
setChanged();
notifyObservers(new SGObjectAddedToListModification("children", child));
}
public void removeFromChildren(HibernateEntity child) {
if (children.remove(child)) {
setChanged();
notifyObservers(new SGObjectRemovedFromListModification("children", child));
}
}
public HibernateModel getHibernateModel() {
return hibernateModel;
}
/**
* Called only from HibernateImplementation at deserialisation or at entity creation
*
* @param hibernateModel
*/
protected void setHibernateModel(HibernateModel hibernateModel) {
this.hibernateModel = hibernateModel;
updateTableName();
}
/**
* {@inheritDoc}
*/
@Override
public TechnologyModuleImplementation getTechnologyModuleImplementation() {
return getHibernateModel().getTechnologyModuleImplementation();
}
}