changeset 33:e52f593f9e0d

new transaction logger "openmind.transactionlog" logging entity save actions and their data. more comments in code.
author casties
date Fri, 26 Aug 2016 11:42:41 +0200
parents 9c54842f5e86
children 5737ab564b94
files src/main/java/org/mpi/openmind/cache/WrapperService.java src/main/java/org/mpi/openmind/repository/bo/Attribute.java src/main/java/org/mpi/openmind/repository/bo/Entity.java src/main/java/org/mpi/openmind/repository/bo/Node.java src/main/java/org/mpi/openmind/repository/bo/Relation.java src/main/java/org/mpi/openmind/repository/services/AbstractPersistenceService.java
diffstat 6 files changed, 239 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/mpi/openmind/cache/WrapperService.java	Thu Aug 25 11:29:47 2016 +0200
+++ b/src/main/java/org/mpi/openmind/cache/WrapperService.java	Fri Aug 26 11:42:41 2016 +0200
@@ -576,15 +576,15 @@
 		return rel;
 	}
 
-	/*
-	 * public Entity saveDefinition(Entity def, String user){ long start =
-	 * System.currentTimeMillis(); def.setObjectClass(Node.TYPE_TBOX);
-	 * def.setUser(user);
+	/**
+	 * Save the given entity as a separate new entity with a new ID.
+	 * 
+	 * Keeps attributes and relations as copies.
 	 * 
-	 * boolean b = this.searchServ.saveEntity(def);
-	 * this.cache.saveDefinition(def);
-	 * logger.info("saveEntityAsNew - execution time[ms]: " +
-	 * (System.currentTimeMillis() - start)); return (Entity)def.clone(); }
+	 * @param entity
+	 * @param user
+	 * @return
+	 * @throws Exception
 	 */
 	public Entity saveEntityAsNew(Entity entity, String user) throws Exception {
 		long start = System.currentTimeMillis();
@@ -647,6 +647,15 @@
 		
 	}
 
+    /**
+     * Returns if this entity has wrong relations.
+     * 
+     * Wrong are source relations whose target doesn't exist.
+     * Similarly for target relations.
+     * 
+     * @param ent
+     * @return
+     */
 	private boolean hasWrongRelations(Entity ent) {
 		for (Relation srcRel : ent.getSourceRelations()) {
 			if (getEntityById(srcRel.getTargetId()) == null) {
@@ -662,28 +671,33 @@
 		return false;
 	}
 
-	private Entity removeWrongRelations(Entity ent) {
-		
-		for (Relation srcRel : new ArrayList<Relation>(ent.getSourceRelations())) {
-			if (srcRel.getTargetId() == null || getEntityByIdReadOnly(srcRel.getTargetId()) == null) {
-				ent.getSourceRelations().remove(srcRel);
-				logger.error(
-					"Inconsistency detected saving entity ["
-							+ ent.getId() + "] " + srcRel.toString());
-			}
-		}
-		
-		for (Relation tarRel : new ArrayList<Relation>(ent.getTargetRelations())) {
-			if (tarRel.getSourceId() == null || getEntityByIdReadOnly(tarRel.getSourceId()) == null) {
-				ent.getTargetRelations().remove(tarRel);
-				logger.error(
-					"Inconsistency detected saving entity ["
-					+ ent.getId() + "] " + tarRel.toString());
-			}
-		}
+    /**
+     * Remove wrong relations from this entity.
+     * 
+     * Wrong are source relations whose target is null or doesn't exist.
+     * Similarly for target relations.
+     * 
+     * @param ent
+     * @return
+     */
+    private Entity removeWrongRelations(Entity ent) {
 
-		return ent;
-	}
+        for (Relation srcRel : new ArrayList<Relation>(ent.getSourceRelations())) {
+            if (srcRel.getTargetId() == null || getEntityByIdReadOnly(srcRel.getTargetId()) == null) {
+                ent.getSourceRelations().remove(srcRel);
+                logger.error("Inconsistency detected saving entity [" + ent.getId() + "] " + srcRel.toString());
+            }
+        }
+
+        for (Relation tarRel : new ArrayList<Relation>(ent.getTargetRelations())) {
+            if (tarRel.getSourceId() == null || getEntityByIdReadOnly(tarRel.getSourceId()) == null) {
+                ent.getTargetRelations().remove(tarRel);
+                logger.error("Inconsistency detected saving entity [" + ent.getId() + "] " + tarRel.toString());
+            }
+        }
+
+        return ent;
+    }
 
 	public Attribute getDefAttributeByOwnValue(String defOC, String attOW) {
 		for (Attribute att : this.cache.getDefAttributes(defOC)) {
--- a/src/main/java/org/mpi/openmind/repository/bo/Attribute.java	Thu Aug 25 11:29:47 2016 +0200
+++ b/src/main/java/org/mpi/openmind/repository/bo/Attribute.java	Fri Aug 26 11:42:41 2016 +0200
@@ -1,6 +1,7 @@
 package org.mpi.openmind.repository.bo;
 
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -9,6 +10,7 @@
 import javax.persistence.Entity;
 import javax.persistence.Transient;
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang.StringUtils;
 import org.hibernate.annotations.Cache;
 import org.hibernate.annotations.CacheConcurrencyStrategy;
@@ -203,6 +205,7 @@
 		}	
 		return 0;
 	}
+	
     @Override
     public String toString() {
         String rowIdString = (this.getRowId() == null) ? "" : "rowId=" + this.getRowId() + ", ";
@@ -210,4 +213,34 @@
 
         return "Attribute[" + rowIdString + idString + "source=" + this.getSourceId() + ", name=" + this.getObjectClass() + ", ownValue=" + this.getOwnValue() + ", sysStatus=" + this.getSystemStatus() + "]";
     }
+    
+    /**
+     * Returns a String representation with base64-encoded own-value.
+     * 
+     * To be used for the transaction log.
+     * 
+     * @return
+     */
+    public String toEncString() {
+        try {
+            String es = "ATTRIBUTE["
+            + "id=\"" + this.getId() + "\", "
+            + "row-id=\"" + this.getRowId() + "\", "
+            + "name=\"" + this.getObjectClass() + "\", "
+            + "content-type=\"" + this.getContentType() + "\", "
+            + "source-id=\"" + this.getSourceId() + "\", "
+            + "source-mtime=\"" + this.getSourceModif() + "\", "
+            + "source-oc=\"" + this.getSourceObjectClass() + "\", "
+            + "mtime=\"" + this.getModificationTime() + "\", "
+            + "version=\"" + this.getVersion() + "\", "
+            + "user=\"" + this.getUser() + "\", "
+            + "public=\"" + this.getIsPublic() + "\", "
+            + "b64-value=\"" + ((this.getOwnValue() != null) ? Base64.encodeBase64String(this.getOwnValue().getBytes("UTF-8")) : "") + "\"]";
+            return es;
+        } catch (UnsupportedEncodingException e) {
+            // this shouldn't happen
+            e.printStackTrace();
+        }
+        return "!!!ENCODING-ERROR!!!";
+    }
 }
--- a/src/main/java/org/mpi/openmind/repository/bo/Entity.java	Thu Aug 25 11:29:47 2016 +0200
+++ b/src/main/java/org/mpi/openmind/repository/bo/Entity.java	Fri Aug 26 11:42:41 2016 +0200
@@ -1,12 +1,14 @@
 package org.mpi.openmind.repository.bo;
 
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.DiscriminatorValue;
 import javax.persistence.Transient;
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.hibernate.annotations.Cache;
@@ -783,6 +785,9 @@
         }
     }
     
+    /**
+     * Sets the ID of the entity and its attributes and relations to null.
+     */
     public void resetId() {
         this.setId(null);
         for (Attribute att : this.attributes) {
@@ -921,6 +926,9 @@
         }
     }
 
+    /**
+     * Set the system_status of this Entity and its attributes and relations.
+     */
     @Override
     public void setSystemStatus(String status) {
         super.setSystemStatus(status);
@@ -977,6 +985,32 @@
                 ", type=" + this.getType() + " att.size=" + this.attributes.size() + "]";
     }
 
+    /**
+     * Returns a String representation with base64-encoded own-value.
+     * 
+     * To be used for the transaction log.
+     * 
+     * @return
+     */
+    public String toEncString() {
+        try {
+            String es = "ENTITY["
+            + "id=\"" + this.getId() + "\", "
+            + "row-id=\"" + this.getRowId() + "\", "
+            + "object-class=\"" + this.getObjectClass() + "\", "
+            + "mtime=\"" + this.getModificationTime() + "\", "
+            + "version=\"" + this.getVersion() + "\", "
+            + "user=\"" + this.getUser() + "\", "
+            + "public=\"" + this.getIsPublic() + "\", "
+            + "b64-value=\"" + ((this.getOwnValue() != null) ? Base64.encodeBase64String(this.getOwnValue().getBytes("UTF-8")) : "") + "\"]";
+            return es;
+        } catch (UnsupportedEncodingException e) {
+            // this shouldn't happen
+            e.printStackTrace();
+        }
+        return "!!!ENCODING-ERROR!!!";
+    }
+
     public String getShortString(){
     	return "[" + this.getId() + "] " + this.getOwnValue();
     }
--- a/src/main/java/org/mpi/openmind/repository/bo/Node.java	Thu Aug 25 11:29:47 2016 +0200
+++ b/src/main/java/org/mpi/openmind/repository/bo/Node.java	Fri Aug 26 11:42:41 2016 +0200
@@ -267,6 +267,11 @@
         return systemStatus;
     }
 
+    /**
+     * Set the system_status of this Node.
+     * 
+     * @param systemStatus
+     */
     public void setSystemStatus(String systemStatus) {
         this.systemStatus = systemStatus;
     }
--- a/src/main/java/org/mpi/openmind/repository/bo/Relation.java	Thu Aug 25 11:29:47 2016 +0200
+++ b/src/main/java/org/mpi/openmind/repository/bo/Relation.java	Fri Aug 26 11:42:41 2016 +0200
@@ -1,6 +1,7 @@
 package org.mpi.openmind.repository.bo;
 
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -8,6 +9,7 @@
 import javax.persistence.DiscriminatorValue;
 import javax.persistence.Transient;
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang.StringUtils;
 import org.hibernate.annotations.Cache;
 import org.hibernate.annotations.CacheConcurrencyStrategy;
@@ -257,7 +259,40 @@
         		"sysStatus=" + this.getSystemStatus() + "]";
     }
 
-	@Override
+    /**
+     * Returns a String representation with base64-encoded own-value.
+     * 
+     * To be used for the transaction log.
+     * 
+     * @return
+     */
+    public String toEncString() {
+        try {
+            String es = "RELATION["
+            + "id=\"" + this.getId() + "\", "
+            + "row-id=\"" + this.getRowId() + "\", "
+            + "object_class=\"" + this.getObjectClass() + "\", "
+            + "source-id=\"" + this.getSourceId() + "\", "
+            + "source-mtime=\"" + this.getSourceModif() + "\", "
+            + "source-oc=\"" + this.getSourceObjectClass() + "\", "
+            + "target-id=\"" + this.getTargetId() + "\", "
+            + "target-mtime=\"" + this.getTargetModif() + "\", "
+            + "target-oc=\"" + this.getTargetObjectClass() + "\", "
+            + "mtime=\"" + this.getModificationTime() + "\", "
+            + "version=\"" + this.getVersion() + "\", "
+            + "user=\"" + this.getUser() + "\", "
+            + "public=\"" + this.getIsPublic() + "\", "
+            + "b64-value=\"" + ((this.getOwnValue() != null) ? Base64.encodeBase64String(this.getOwnValue().getBytes("UTF-8")) : "") + "\"]";
+            return es;
+        } catch (UnsupportedEncodingException e) {
+            // this shouldn't happen
+            e.printStackTrace();
+        }
+        return "!!!ENCODING-ERROR!!!";
+    }
+
+    
+    @Override
 	public int compareTo(Relation e) {
 		if(e == null)
 			return 1;
--- a/src/main/java/org/mpi/openmind/repository/services/AbstractPersistenceService.java	Thu Aug 25 11:29:47 2016 +0200
+++ b/src/main/java/org/mpi/openmind/repository/services/AbstractPersistenceService.java	Fri Aug 26 11:42:41 2016 +0200
@@ -25,16 +25,19 @@
  */
 public abstract class AbstractPersistenceService {
 
-	private ConfigurationService configurationService;
+    private ConfigurationService configurationService;
 
 	private OwnValueGenerator ownValueGenerator;
 
 	private final static String NODE_SEQUENCE = "nodeSequence";
 
-	private static Logger logger = Logger
-			.getLogger(AbstractPersistenceService.class);
+	private static Logger logger = Logger.getLogger(AbstractPersistenceService.class);
+	
+    public static final String TRANSACTION_LOGGER = "openmind.transactionlog";
 
-	private boolean importModus = false;
+    private static Logger txLog = Logger.getLogger(TRANSACTION_LOGGER);
+
+	private boolean importMode = false;
 
 	/*
 	 * static { logger.setLevel(Level.DEBUG); PatternLayout layout = new
@@ -562,54 +565,17 @@
 
 				Entity previousEntity = previousEntityList.get(0);
 				logger.info("Saving previous entity: " + previousEntity);
-				this.savePreviousEntity(session, previousEntity);
+				this.persistEntityAsPrevious(session, previousEntity);
 			}
 		}
 		session.getTransaction().commit();
 	}
 
-	/*
-	 * public void removeEntity(Long entId, String type) {
-	 * logger.info("Deleting entity [ID=" + entId + ", type=" + type +
-	 * "]. But keeping history in DB."); Session session =
-	 * HibernateUtil.getSessionFactory().getCurrentSession();
-	 * session.getTransaction().begin();
-	 * 
-	 * if (entId != null) { List<Entity> previousEntityList =
-	 * this.getEntities(session, entId, Node.SYS_STATUS_CURRENT_VERSION, type,
-	 * null); if (previousEntityList.size() > 0) { if (previousEntityList.size()
-	 * > 1) { System.err .println(
-	 * "[PersistenceService.saveEntity] found more than one current entities!");
-	 * }
-	 * 
-	 * Entity previousEntity = previousEntityList.get(0);
-	 * logger.info("Saving previous entity: " + previousEntity);
-	 * this.savePreviousEntity(session, previousEntity); } } }
-	 */
-
-	public void savePreviousEntity(Entity entity) throws Exception {
-
-		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-		session.getTransaction().begin();
-
-		if (entity.getId() != null) {
-			List<Entity> previousEntityList = this.getEntities(session,
-					entity.getId(), Node.SYS_STATUS_CURRENT_VERSION,
-					entity.getType(), null, false);
-			if (previousEntityList.size() > 0) {
-				if (previousEntityList.size() > 1) {
-					logger.error("[PersistenceService.saveEntity] found more than one current entities!");
-				}
-				Entity previousEntity = previousEntityList.get(0);
-				logger.debug("Saving previous entity: " + previousEntity);
-				this.savePreviousEntity(session, previousEntity);
-			}
-		}
-		this.saveCurrentEntity(session, entity, null);
-		session.getTransaction().commit();
-	}
 
 	/**
+	 * Save the entity to the database.
+	 * 
+	 * Creates a new version of the entity. Runs in a transaction.
 	 * 
 	 * @param entity
 	 * @return
@@ -625,6 +591,15 @@
 
 	}
 
+	/**
+	 * Save the entity to the database using the given session.
+	 * 
+	 * Creates a new version and sets the existing entity to PREVIOUS_VERSION.
+	 * 
+	 * @param session
+	 * @param entity
+	 * @throws Exception
+	 */
 	private void saveEntity0(Session session, Entity entity) throws Exception {
 		if (entity.getId() != null) {
 			List<Entity> previousEntityList = this.getEntities(session, entity.getId(), Node.SYS_STATUS_CURRENT_VERSION, entity.getType(), null, false);
@@ -635,12 +610,23 @@
 
 				Entity previousEntity = previousEntityList.get(0);
 				logger.info("Saving previous entity: " + previousEntity);
-				this.savePreviousEntity(session, previousEntity);
+				this.persistEntityAsPrevious(session, previousEntity);
 			}
 		}
 		this.saveCurrentEntity(session, entity, null);
 	}
 
+	/**
+	 * Save the entity as (new) current version using the given session.
+	 * 
+	 * Sets system_status to CURRENT_VERSION and updates row_id, version, modification_time,
+	 * etc.
+	 * 
+	 * @param session
+	 * @param entity
+	 * @param idSequence
+	 * @throws Exception
+	 */
 	private void saveCurrentEntity(Session session, Entity entity,
 			Sequence idSequence) throws Exception {
 		Long time = System.currentTimeMillis();
@@ -654,12 +640,17 @@
 		entity.autoNormalize();
 		// generating of id, connecting rels, atts and views to the entity
 		this.prepareEntity(session, entity, idSequence);
-		this.saveEntity(session, entity);
+		this.persistEntity(session, entity);
 	}
 
 	/**
-	 * Here the modification time will be propagated from the entity to its
-	 * relations an attributes.
+	 * Update the entity to prepare it for persisting.
+	 * 
+	 * If the ID is null new IDs will be assigned for the entity and its 
+	 * attributes and relations.
+	 * The modification time is propagated from the entity to its
+	 * attributes and relations.
+	 * Own-values are normalized.
 	 * 
 	 * @param session
 	 * @param entity
@@ -772,42 +763,57 @@
 	}
 
 	/**
-	 * Saves an entity setting its system state as previous_version
+	 * Set an entities' system state to PREVIOUS_VERSION and persist it.
+	 * 
+	 * Also persists the entities' attributes and relations.
 	 * 
 	 * @param session
 	 * @param entity
 	 */
-	private void savePreviousEntity(Session session, Entity entity) {
+	private void persistEntityAsPrevious(Session session, Entity entity) {
 		entity.setSystemStatus(Node.SYS_STATUS_PREVIOUS_VERSION);
+        txLog.debug("* START save previous entity...");
+        txLog.info("save previous entity: "+entity.toEncString());
 		session.save(entity);
 		for (Attribute attribute : entity.getAttributes()) {
-            logger.debug("  saving prev entity attribute: "+attribute);
+            txLog.info("save previous entity attribute: "+attribute.toEncString());
 			session.save(attribute);
 		}
 		for (Relation rel : entity.getSourceRelations()) {
+	        txLog.info("save previous source relation: "+rel.toEncString());
 			session.save(rel);
 			for (Attribute att : rel.getAttributes()) {
-	            logger.debug("  saving prev (source)relation attribute: "+rel);
+                txLog.info("save previous source relation attribute: "+att.toEncString());
 				session.save(att);
 			}
 		}
 		for (Relation rel : entity.getTargetRelations()) {
+            txLog.info("save previous target relation: "+rel.toEncString());
 			session.save(rel);
             for (Attribute att : rel.getAttributes()) {
-                logger.debug("  saving prev (target)relation attribute: "+rel);
+                txLog.info("save previous target relation attribute: "+att.toEncString());
                 session.save(att);
             }
 		}
 		for (View view : entity.getViews()) {
 			session.save(view);
 		}
+        txLog.debug("* End ...save previous entity");
 	}
 
-	private void saveEntity(Session session, Entity entity) throws Exception {
-		logger.info("Saving current entity: " + entity);
+	/**
+	 * Persist a (current) entity and its attributes and relations.
+	 * 
+	 * @param session
+	 * @param entity
+	 * @throws Exception
+	 */
+	private void persistEntity(Session session, Entity entity) throws Exception {
+		txLog.info("* START save entity...");
+        txLog.info("save entity: "+entity.toEncString());
 		session.save(entity);
 		for (Attribute attribute : entity.getAttributes()) {
-		    logger.debug("  saving entity attribute: "+attribute);
+		    txLog.info("save entity attribute: "+attribute.toEncString());
 			session.save(attribute);
 		}
 		for (Relation rel : entity.getSourceRelations()) {
@@ -817,9 +823,10 @@
 						"Either the sourceId or the targetId was not initialized to the source relation: "
 								+ rel.getOwnValue());
 			}
+	        txLog.info("save source relation: "+rel.toEncString());
 			session.save(rel);
 			for (Attribute att : rel.getAttributes()) {
-	            logger.debug("  saving (source)relation attribute: "+att);
+	            txLog.info("save source relation attribute: "+att.toEncString());
 				session.save(att);
 			}
 		}
@@ -830,9 +837,10 @@
 						"Either the sourceId or the targetId was not initialized to the target relation: "
 								+ rel.getOwnValue());
 			}
+            txLog.info("save target relation: "+rel.toEncString());
 			session.save(rel);
             for (Attribute att : rel.getAttributes()) {
-                logger.debug("  saving (target)relation attribute: "+att);
+                txLog.info("save target relation attribute: "+att.toEncString());
                 session.save(att);
             }
 		}
@@ -840,15 +848,15 @@
 		// Call of ownValue Generator.
 		// TODO: the method should be used always? what would happen if the
 		// ownValue returns null?
-		if (!isImportModus()) {
-			String ownValue = this.getOwnValueGenerator().generateOwnValue(
-					entity, session);
+		if (!isImportMode()) {
+			String ownValue = this.getOwnValueGenerator().generateOwnValue(entity, session);
 			if (StringUtils.isNotEmpty(ownValue)) {
 				entity.setOwnValue(ownValue);
 				entity.autoNormalize();
 				session.save(entity);
 			}
 		}
+        txLog.debug("* ...END save entity");
 	}
 
 	public OwnValueGenerator getOwnValueGenerator() {
@@ -861,7 +869,7 @@
 
 	/**
 	 * <p>
-	 * Returns entities with their corresponded contain.
+	 * Returns entities with their corresponding contents.
 	 * </p>
 	 * 
 	 * @param session
@@ -927,7 +935,7 @@
 
 	/**
 	 * <p>
-	 * Returns entities with their corresponded contain.
+	 * Returns entities with their corresponding content.
 	 * </p>
 	 * 
 	 * @param id
@@ -1055,7 +1063,10 @@
 			entity.setSourceRelations(new ArrayList<Relation>());
 			entity.setTargetRelations(new ArrayList<Relation>());
 
-            // FIXME: getNodes finds all attributes if id=null!
+            /*
+             * Danger: getNodes finds all attributes in the db and tries to attach them to 
+             * this entity if id=null!
+             */
             if (entity.getId() == null) {
                 logger.error("Entity with id=null! Abort loading attributes.");
                 return entity;
@@ -1080,7 +1091,10 @@
 				} else if (node instanceof Relation) {
 					Relation rel = (Relation) node;
 					// new attr for relations
-					// FIXME: getNodes finds all attributes if id=null!
+		            /*
+		             * Danger: getNodes finds all attributes in the db and tries to attach them to 
+		             * this relation if id=null!
+		             */
 		            if (rel.getId() == null) {
 		                logger.error("Relation with id=null! Abort loading attributes.");
 		                continue;
@@ -1101,8 +1115,7 @@
 				} else if (node instanceof View) {
 					entity.getViews().add((View) node);
 				} else {
-					throw new IllegalArgumentException("Invalid node found: "
-							+ node);
+					throw new IllegalArgumentException("Invalid node found: " + node);
 				}
 			}
 
@@ -1123,7 +1136,10 @@
 				if (node instanceof Relation) {
 					Relation rel = (Relation) node;
 					// new attr for relations
-		            // FIXME: getNodes finds all attributes if id=null!
+		            /*
+		             * Danger: getNodes finds all attributes in the db and tries to attach them to 
+		             * this relation if id=null!
+		             */
 		            if (rel.getId() == null) {
 		                logger.error("Relation with id=null! Abort loading attributes.");
 		                continue;
@@ -1433,12 +1449,12 @@
 		this.configurationService = configurationService;
 	}
 
-	public boolean isImportModus() {
-		return importModus;
+	public boolean isImportMode() {
+		return importMode;
 	}
 
 	public void setImportModus(boolean importModus) {
-		this.importModus = importModus;
+		this.importMode = importModus;
 	}
 
 	// #################################################################