package org.jblooming.ontology.businessLogic;
import org.hibernate.*;
import org.hibernate.engine.CascadesProxy;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
import org.hibernate.type.OneToOneType;
import org.hibernate.type.Type;
import org.jblooming.PlatformRuntimeException;
import org.jblooming.messaging.Listener;
import org.jblooming.ontology.*;
import org.jblooming.oql.OqlQuery;
import org.jblooming.oql.QueryHelper;
import org.jblooming.persistence.PersistenceHome;
import org.jblooming.persistence.exceptions.PersistenceException;
import org.jblooming.persistence.exceptions.RemoveException;
import org.jblooming.persistence.exceptions.FindByPrimaryKeyException;
import org.jblooming.persistence.hibernate.HibernateFactory;
import org.jblooming.persistence.hibernate.HibernateUtilities;
import org.jblooming.persistence.hibernate.PersistenceContext;
import org.jblooming.tracer.Tracer;
import org.jblooming.utilities.ReflectionUtilities;
import org.jblooming.waf.constants.Commands;
import org.jblooming.waf.constants.ObjectEditorConstants;
import org.jblooming.waf.view.ClientEntries;
import org.jblooming.waf.view.ClientEntry;
import org.jblooming.waf.view.PageState;
import java.lang.reflect.InvocationTargetException;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;
import java.io.Serializable;
public class DeleteHelper {
/**
* This method should be used when
* @param delendo
* @param pageState
* @param propertyName_command one or more Pair (name_of_the_property, command) where command is one of Commands.UNLINK, Commands.UP, Commands.DELETE_DESCENDANTS
*/
public void cmdDeleteForced(IdentifiableSupport delendo,PageState pageState, Pair... propertyName_command) throws PersistenceException {
for (Pair nc:propertyName_command){
pageState.addClientEntry(ObjectEditorConstants.FLD_DELETE_STYLE + "__" + nc.first,nc.second+"");
}
cmdDelete(delendo,pageState);
}
public static void cmdDelete(IdentifiableSupport delendo, PageState pageState) throws PersistenceException {
try {
delendo = (IdentifiableSupport) ReflectionUtilities.getUnderlyingObject(delendo);
boolean delendaIsNode = delendo instanceof Node;
Node parent = null;
if (delendaIsNode)
parent = ((Node) delendo).getParentNode();
final ClientEntries clientEntries = pageState.getClientEntries();
Set cesKeys = clientEntries.getEntryKeys();
Class objClass = delendo.getClass();
String clazzName = PersistenceHome.deProxy(objClass.getName());
objClass = Class.forName(clazzName);
PersistenceContext persistenceContext = PersistenceContext.get(delendo);
SessionFactory sf = persistenceContext.persistenceConfiguration.getSessionFactory();
EntityPersister entityPersister = null;
entityPersister = (EntityPersister) sf.getClassMetadata(objClass);
PersistentClass pclass = HibernateUtilities.getClassMapping(objClass);
List<Property> allProps = new ArrayList();
Iterator it = pclass.getPropertyClosureIterator();
while (it.hasNext()) {
allProps.add((Property) it.next());
}
CascadesProxy csp = new CascadesProxy();
//String[] names = entityPersister.getPropertyNames();
for (Property property : allProps) {
String name = property.getName();
EntityMode mode = PersistenceContext.get(delendo).session.getEntityMode();
Object propertyValue = entityPersister.getPropertyValue(delendo, name, mode);
if (propertyValue != null) {
if (propertyValue instanceof Collection && ((Collection) propertyValue).size() > 0) {
Collection coll = (Collection) propertyValue;
Object sample = coll.iterator().next();
boolean membersAreChildren = delendaIsNode && coll.equals(((Node) delendo).getChildrenNode());
if (sample instanceof Identifiable) {
if (cesKeys != null && cesKeys.size() > 0) {
final ClientEntry entry = clientEntries.getEntry(ObjectEditorConstants.FLD_DELETE_STYLE + "__" + name);
boolean globalUnlinkForThisColl = entry != null && entry.stringValueNullIfEmpty() != null && Commands.UNLINK.equals(entry.stringValueNullIfEmpty());
boolean globalUpForThisColl = entry != null && entry.stringValueNullIfEmpty() != null && Commands.UP.equals(entry.stringValueNullIfEmpty());
boolean globalDelDescForThisColl = entry != null && entry.stringValueNullIfEmpty() != null && Commands.DELETE_DESCENDANTS.equals(entry.stringValueNullIfEmpty());
for (Iterator iterator = new ArrayList(coll).iterator(); iterator.hasNext();) {
Identifiable memberOfCollection = (Identifiable) iterator.next();
String selectedCommand = pageState.getEntry(ObjectEditorConstants.FLD_DELETE_STYLE + "__" + name + "__" + memberOfCollection.getId()).stringValueNullIfEmpty();
boolean doesPropertyCascade = csp.doesCascadeOnDelete(property.getCascadeStyle());
// move to root
if (globalUnlinkForThisColl || Commands.UNLINK.equals(selectedCommand)) {
//remove from this collection if is no cascade
if (!doesPropertyCascade)
coll.remove(memberOfCollection);
if (membersAreChildren) {
if (memberOfCollection instanceof PerformantNode)
((PerformantNodeSupport) memberOfCollection).setParentAndStore(null);
else
((Node) memberOfCollection).setParentNode(null);
}
//move to parent
} else if (globalUpForThisColl || Commands.UP.equals(selectedCommand)) {
//remove from this collection if is no cascade
if (!doesPropertyCascade)
coll.remove(memberOfCollection);
if (membersAreChildren) {
if (memberOfCollection instanceof PerformantNode)
((PerformantNodeSupport) memberOfCollection).setParentAndStore((PerformantNodeSupport) parent);
else {
((Node) memberOfCollection).setParentNode(parent);
//add to parent's collection
((Collection) entityPersister.getPropertyValue(parent, name, mode)).add(memberOfCollection);
}
} else {
//add to parent's collection
((Collection) entityPersister.getPropertyValue(parent, name, mode)).add(memberOfCollection);
}
//delete also members
} else if (globalDelDescForThisColl || Commands.DELETE_DESCENDANTS.equals(selectedCommand)) {
//remove from this collection if is no cascade
if (!doesPropertyCascade)
coll.remove(memberOfCollection);
final Node node = (Node) memberOfCollection;
if (membersAreChildren) {
node.setParentNode(null);
recursivelyDeleteNode(node, pageState);
} else
deleteIdentifiable((IdentifiableSupport)memberOfCollection, pageState);
}
}
}
}
}
}
}
deleteIdentifiable(delendo, pageState);
} catch (ClassNotFoundException e) {
throw new PlatformRuntimeException(e);
} catch (HibernateException e) {
throw new PlatformRuntimeException(e);
}
}
private static void deleteIdentifiable(IdentifiableSupport ident, PageState ps) throws RemoveException {
PersistenceContext dpc = PersistenceContext.get(ident);
try {
ident.remove();
dpc.session.flush();
// delete all relative listeners
QueryHelper qh = new QueryHelper("from " + Listener.class.getName());
qh.addQBEClause("theClass", "theClass", ident.getClass().getName(), QueryHelper.TYPE_CHAR);
qh.addQBEClause("identifiableId", "identifiableId", ident.getId().toString(), QueryHelper.TYPE_CHAR);
} catch (Throwable e) {
Transaction t = dpc.session.getTransaction();
if (t != null && !t.wasRolledBack()) {
t.rollback();
dpc.session.beginTransaction();
}
Serializable id = ident.getId();
Class cl = ReflectionUtilities.getUnderlyingObjectClass(ident);
// 3Dec2007 changed to clear: evict could leave cascading refences "alive" and set as deleted
//dpc.session.evict(ident);
dpc.session.clear();
try {
ident = (IdentifiableSupport) PersistenceHome.findByPrimaryKey(cl, id);
} catch (FindByPrimaryKeyException e1) {
}
ps.setMainObjectId(ident.getId());
ps.setMainObject(ident);
ps.resetLoggedOperator();
throw new RemoveException(e);
}
}
public static void recursivelyDeleteNode(Node node, PageState ps) throws RemoveException {
Collection children = node.getChildrenNode();
if (children != null && children.size() > 0) {
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
Node child = (Node) iterator.next();
recursivelyDeleteNode(child, ps);
}
}
deleteIdentifiable((IdentifiableSupport)node, ps);
}
public static void cmdDisintegrate(Collection disintegrandas) throws PersistenceException {
for (Object r : disintegrandas) {
DeleteHelper.cmdDisintegrate((IdentifiableSupport) r);
}
}
public static void cmdDisintegrate(IdentifiableSupport delendo) throws PersistenceException {
PersistenceContext pc = new PersistenceContext();
Object underlyingObject = ReflectionUtilities.getUnderlyingObjectAsObject(delendo);
Object value = null;
try {
value = underlyingObject.getClass().getMethod("getId").invoke(underlyingObject);
} catch (Exception e) {
throw new PlatformRuntimeException(e);
}
Object realDelendo = null;
try {
realDelendo = PersistenceHome.findUniqueObject(underlyingObject.getClass(), "id", value, pc);
} finally {
pc.commitAndClose();
}
pc = new PersistenceContext();
Class realClass = realDelendo.getClass();
Map<String, org.hibernate.mapping.Collection> inverses = HibernateUtilities.getAllInversesOnTarget(realDelendo);
PersistenceContext persistenceContext = PersistenceContext.get(delendo);
SessionFactory sf = persistenceContext.persistenceConfiguration.getSessionFactory();
PersistentClass realClassPc = HibernateUtilities.getClassMapping(realClass);
CascadesProxy csp = new CascadesProxy();
Iterator i = persistenceContext.persistenceConfiguration.getHibernateConfiguration().getClassMappings();
while (i.hasNext()) {
PersistentClass persistentClass = (PersistentClass) i.next();
Iterator j = persistentClass.getPropertyClosureIterator();
while (j.hasNext()) {
Property property = (Property) j.next();
Column col = null;
if (property.getColumnIterator().hasNext())
col = (Column) property.getColumnIterator().next();
//is there a cascading inverse for this property on realClass ?
boolean cascadingInverseOnRealClass = false;
for (String key : inverses.keySet()) {
org.hibernate.mapping.Collection hibInvCollOfDelendo = inverses.get(key);
try {
Property propertyWhichIsCollection = realClassPc.getProperty(key);
if (((Column) (hibInvCollOfDelendo.getKey().getColumnIterator().next())).getName().equals(property.getName()) &&
csp.doesCascadeOnDelete(propertyWhichIsCollection.getCascadeStyle())
) {
cascadingInverseOnRealClass = true;
break;
}
} catch (MappingException e) {
}
}
boolean isNullable = property.getValue().isNullable();
//remove references from entities to delendo
if (
!cascadingInverseOnRealClass &&
isNullable &&
property.getType() instanceof EntityType &&
! (property.getType() instanceof OneToOneType) &&
property.getType().getReturnedClass() != null &&
//property.getType().getReturnedClass().getName().equals(realClass.getName()) &&
realClassPc.getTable().getName().equals(HibernateUtilities.getTableName(property.getType().getReturnedClass())) &&
//ReflectionUtilities.extendsOrImplements(realClass, property.getType().getReturnedClass()) &&
!csp.doesCascadeOnDelete(property.getCascadeStyle())
) {
String hql = "update " + persistentClass.getEntityName() + " set " + property.getName() + "=null where " + property.getName() + " = :disintegrando";
OqlQuery oql = new OqlQuery(hql, pc);
oql.getQuery().setEntity("disintegrando", realDelendo);
Tracer.platformLogger.debug("cmdDisintegrate reference " + hql);
oql.getQuery().executeUpdate();
//remove references to delendo from non inverse external collections
} else if (
property.getType() instanceof CollectionType
) {
Type elementType = ((CollectionType) property.getType()).getElementType((SessionFactoryImplementor) sf);
if (elementType.isEntityType()) {
Class collectionOf = elementType.getReturnedClass();
String tableName = HibernateUtilities.getTableName(collectionOf);
if (tableName != null && realClassPc.getTable().getName().equals(tableName)) {
org.hibernate.mapping.Collection collection = persistenceContext.persistenceConfiguration.getHibernateConfiguration().getCollectionMapping(((CollectionType) property.getType()).getRole());
if (!collection.isInverse()) {
String valueColumn = ((Column) collection.getElement().getColumnIterator().next()).getName();
PreparedStatement ps = null;
try {
String sql = "DELETE FROM " + collection.getCollectionTable().getName() + " WHERE " + valueColumn + "= ?";
ps = pc.session.connection().prepareStatement(sql);
Tracer.platformLogger.debug("cmdDisintegrate CollectionType " + sql);
//ps.setString(1, realDelendo.getId().toString());
ps.setString(1, realDelendo.getClass().getMethod("getId").invoke(realDelendo).toString());
ps.executeUpdate();
ps.close();
} catch (SQLException e) {
throw new PlatformRuntimeException(e);
} catch (NoSuchMethodException e) {
throw new PlatformRuntimeException(e);
} catch (IllegalAccessException e) {
throw new PlatformRuntimeException(e);
} catch (InvocationTargetException e) {
throw new PlatformRuntimeException(e);
}
}
}
}
}
}
}
pc.session.delete(realDelendo);
pc.commitAndClose();
}
}
//}