historized feature
diff --git a/org.eclipse.osbp.jpa.services.feature/feature.xml b/org.eclipse.osbp.jpa.services.feature/feature.xml
index 81c4ed3..936f12c 100644
--- a/org.eclipse.osbp.jpa.services.feature/feature.xml
+++ b/org.eclipse.osbp.jpa.services.feature/feature.xml
@@ -3,7 +3,8 @@
         id="org.eclipse.osbp.jpa.services.feature"
         label="%featureName"
         version="0.9.0.qualifier"
-        provider-name="%providerName">
+        provider-name="%providerName"
+		plugin="org.eclipse.osbp.license">
         
     <description>
         %description
diff --git a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedDescriptorWrapper.java b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedDescriptorWrapper.java
index 744095f..c62908a 100644
--- a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedDescriptorWrapper.java
+++ b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedDescriptorWrapper.java
@@ -1,10 +1,14 @@
 package org.eclipse.osbp.jpa.services.history;
 
 import java.lang.reflect.Field;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.List;
 
 import javax.persistence.Version;
 
+import org.eclipse.osbp.runtime.common.annotations.DomainKey;
+import org.eclipse.osbp.runtime.common.annotations.HistDomainKey;
 import org.eclipse.osbp.runtime.common.annotations.HistIsCurrent;
 import org.eclipse.osbp.runtime.common.annotations.HistIsCustomVersion;
 import org.eclipse.osbp.runtime.common.annotations.HistValidUntil;
@@ -18,11 +22,15 @@
 
 	private final Class<?> clazz;
 	private final ClassDescriptor descriptor;
+	private final SimpleDateFormat dateFormat;
 	private DatabaseMapping versionMapping;
 	private DatabaseMapping validUntilMapping;
 	private DatabaseMapping currentMapping;
 	private DatabaseMapping isCustomVersionMapping;
 
+	private DatabaseMapping historizedDomainKeyMapping;
+	private DatabaseMapping domainKeyMapping;
+
 	private DatabaseMapping idMapping;
 	private ClassDescriptor uuidHistDescriptor;
 	private DatabaseMapping id_idMapping;
@@ -32,6 +40,9 @@
 		this.clazz = descriptor.getJavaClass();
 		this.descriptor = descriptor;
 
+		// later may be controlled by the descriptor
+		dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+
 		// find the ID String field by the descriptor
 		List<DatabaseField> pk = descriptor.getPrimaryKeyFields();
 		for (DatabaseMapping mapping : descriptor.getMappings()) {
@@ -47,6 +58,8 @@
 		Field validUntilField = BeanUtils.getField(clazz, HistValidUntil.class);
 		Field currentHist = BeanUtils.getField(clazz, HistIsCurrent.class);
 		Field isCustomVersion = BeanUtils.getField(clazz, HistIsCustomVersion.class);
+		Field historizedDomainKeyField = BeanUtils.getField(clazz, HistDomainKey.class);
+		Field domainKeyField = BeanUtils.getField(clazz, DomainKey.class);
 
 		id_idMapping = uuidHistDescriptor.getMappingForAttributeName("id");
 		id_validFromMapping = uuidHistDescriptor.getMappingForAttributeName("validFrom");
@@ -54,6 +67,9 @@
 		validUntilMapping = descriptor.getMappingForAttributeName(validUntilField.getName());
 		currentMapping = descriptor.getMappingForAttributeName(currentHist.getName());
 		isCustomVersionMapping = descriptor.getMappingForAttributeName(isCustomVersion.getName());
+		versionMapping = descriptor.getMappingForAttributeName(versionField.getName());
+		historizedDomainKeyMapping = descriptor.getMappingForAttributeName(historizedDomainKeyField.getName());
+		domainKeyMapping = descriptor.getMappingForAttributeName(domainKeyField.getName());
 	}
 
 	public String getIdAttName() {
@@ -84,6 +100,10 @@
 		return isCustomVersionMapping.getAttributeName();
 	}
 
+	public String getHistorizedDomainKeyAttName() {
+		return historizedDomainKeyMapping.getAttributeName();
+	}
+
 	public UUIDHist getID(Object obj) {
 		return (UUIDHist) idMapping.getAttributeValueFromObject(obj);
 	}
@@ -120,6 +140,10 @@
 		return (boolean) isCustomVersionMapping.getAttributeValueFromObject(obj);
 	}
 
+	public String getHistorizedDomainKey(Object obj) {
+		return (String) historizedDomainKeyMapping.getAttributeValueFromObject(obj);
+	}
+
 	public Class<?> getEntityClass() {
 		return descriptor.getJavaClass();
 	}
@@ -164,4 +188,21 @@
 		isCustomVersionMapping.setAttributeValueInObject(obj, value);
 	}
 
+	public void setHistorizedDomainKey(Object obj, String value) {
+		historizedDomainKeyMapping.setAttributeValueInObject(obj, value);
+	}
+
+	public void applyHistorizedDomainKey(Object obj) {
+		if (domainKeyMapping == null) {
+			return;
+		}
+
+		String domainKey = (String) domainKeyMapping.getAttributeValueFromObject(obj);
+		Date date = new Date(getId_ValidFrom(obj));
+
+		String histDomainKey = domainKey + "-" + dateFormat.format(date);
+		setHistorizedDomainKey(obj, histDomainKey);
+
+	}
+
 }
diff --git a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedObjectWrapper.java b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedObjectWrapper.java
index a8173d9..0d077ff 100644
--- a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedObjectWrapper.java
+++ b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedObjectWrapper.java
@@ -24,8 +24,6 @@
 		return delegate.getVersionAttName();
 	}
 
-	
-	
 	public String getId_IdAttName() {
 		return delegate.getId_IdAttName();
 	}
@@ -106,4 +104,20 @@
 		delegate.setCustomVersion(obj, value);
 	}
 
+	public String getHistorizedDomainKeyAttName() {
+		return delegate.getHistorizedDomainKeyAttName();
+	}
+
+	public String getHistorizedDomainKey() {
+		return delegate.getHistorizedDomainKey(obj);
+	}
+
+	public void setHistorizedDomainKey(String value) {
+		delegate.setHistorizedDomainKey(obj, value);
+	}
+
+	public void applyHistorizedDomainKey() {
+		delegate.applyHistorizedDomainKey(obj);
+	}
+
 }
diff --git a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedQueryRedirector.java b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedQueryRedirector.java
index 96168f5..286587d 100644
--- a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedQueryRedirector.java
+++ b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistorizedQueryRedirector.java
@@ -17,17 +17,26 @@
 import org.eclipse.persistence.queries.WriteObjectQuery;
 import org.eclipse.persistence.sessions.Record;
 import org.eclipse.persistence.sessions.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Manages the versioning of historized and timedependent entities.
  */
 @SuppressWarnings("serial")
 public class HistorizedQueryRedirector implements QueryRedirector {
+	protected static Logger logger = LoggerFactory.getLogger(HistorizedQueryRedirector.class);
 
 	@Override
 	public Object invokeQuery(DatabaseQuery query, Record arguments, Session session) {
 		WriteObjectQuery writeObjectQuery = (WriteObjectQuery) query;
-
+		
+		logger.debug("historized changes {}", writeObjectQuery.getObjectChangeSet().getChanges());
+		
+		if(writeObjectQuery instanceof UpdateObjectQuery) {
+			return writeObjectQuery.getObject();
+		}
+		
 		Object persistedObj = writeObjectQuery.getObject();
 
 		// the object that was persisted / merged
@@ -35,32 +44,40 @@
 		HistorizedObjectWrapper persistedObjWrapper = new HistorizedObjectWrapper(writeObjectQuery.getDescriptor(),
 				persistedObj);
 
-		if (persistedObjWrapper.getVersion() > 1) {
-			throw new IllegalArgumentException(
-					"Version must be 0. Changing historized records is not allowed: " + persistedObj.toString());
-		}
+//		if (persistedObjWrapper.getVersion() > 1) {
+//			throw new IllegalArgumentException(
+//					"Version must be 0. Changing historized records is not allowed: " + persistedObj.toString());
+//		}
 		Object current = getCurrent(persistedObjWrapper, (AbstractSession) session);
 
 		if (current == null) {
 			persistedObjWrapper.setId_ValidFrom(createNow(persistedObjWrapper));
 			persistedObjWrapper.setValidUntil(getMaxDate());
 			persistedObjWrapper.setCurrentHist(true);
+			
+			persistedObjWrapper.applyHistorizedDomainKey();
 
 			writeObjectQuery.setDoNotRedirect(true);
-			Object newAdr = writeObjectQuery.execute((AbstractSession) session, (AbstractRecord) arguments);
-			return newAdr;
+			return writeObjectQuery.execute((AbstractSession) session, (AbstractRecord) arguments);
 		} else {
 
 			// sleep 1ms for minimum time intervall between historized records
 			try {
 				Thread.sleep(1);
-			} catch (InterruptedException e) {
+			} catch (InterruptedException e) {	// NOSONAR
 			}
 
 			// update the address to be historized
 			long now = createNow(persistedObjWrapper);
 			Object histCurrentObj = getCurrentManaged(
 					new HistorizedObjectWrapper(writeObjectQuery.getDescriptor(), current), (AbstractSession) session);
+			Object histCurrentObjClone = null;
+			try {
+				histCurrentObjClone = histCurrentObj.getClass().newInstance();
+			} catch (InstantiationException | IllegalAccessException e) {
+				logger.error("{}", e);
+			}
+			query.getDescriptor().getObjectBuilder().copyInto(histCurrentObj, histCurrentObjClone);
 
 			// the current object in database with flag histCurrent = true
 			//
@@ -72,24 +89,29 @@
 				return persistedObj;
 			}
 
+			// update the old record
+			//
 			histCurrentObjWrapper.setCurrentHist(false);
 			histCurrentObjWrapper.setValidUntil(now);
 			UpdateObjectQuery updateCurrent = new UpdateObjectQuery(histCurrentObj);
+			updateCurrent.setBackupClone(histCurrentObjClone);
 			updateCurrent.setDoNotRedirect(true);
 			updateCurrent.setIsUserDefined(true);
 			updateCurrent.execute((AbstractSession) session, (AbstractRecord) arguments);
 
+			// insert the new record
+			//
 			persistedObjWrapper.setId_ValidFrom(now);
 			persistedObjWrapper.setValidUntil(getMaxDate());
 			persistedObjWrapper.setCurrentHist(true);
 			persistedObjWrapper.setVersion((int) 0);
+			persistedObjWrapper.applyHistorizedDomainKey();
 
 			InsertObjectQuery insertObjectQ = new InsertObjectQuery(persistedObj);
 			insertObjectQ.setIsUserDefined(true);
 			insertObjectQ.setDoNotRedirect(true);
 
-			Object newAdr = insertObjectQ.execute((AbstractSession) session, (AbstractRecord) arguments);
-			return newAdr;
+			return insertObjectQ.execute((AbstractSession) session, (AbstractRecord) arguments);
 		}
 
 	}
@@ -114,7 +136,7 @@
 		rq.dontCheckCache();
 		rq.dontMaintainCache();
 
-		Object current = (Object) rq.executeInUnitOfWork(uow, EmptyRecord.getEmptyRecord());
+		Object current = rq.executeInUnitOfWork(uow, EmptyRecord.getEmptyRecord());
 
 		uow.clearForClose(true);
 		return current;
@@ -123,14 +145,13 @@
 	private Object getCurrentManaged(HistorizedObjectWrapper wrapper, AbstractSession session) {
 
 		ReadObjectQuery rq = new ReadObjectQuery(wrapper.getEntityClass());
+		rq.conformResultsInUnitOfWork();
 
 		ExpressionBuilder eb = rq.getExpressionBuilder();
 		Expression exp = eb.get(wrapper.getIdAttName()).equal(wrapper.getID());
 		rq.setSelectionCriteria(exp);
 
-		Object current = rq.execute(session, EmptyRecord.getEmptyRecord());
-
-		return current;
+		return rq.execute(session, EmptyRecord.getEmptyRecord());
 	}
 
 	private long getMaxDate() {
diff --git a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistoryFacade.java b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistoryFacade.java
index 0679bdf..1a8a6c6 100644
--- a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistoryFacade.java
+++ b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/history/HistoryFacade.java
@@ -37,6 +37,7 @@
 @SuppressWarnings("rawtypes")
 public class HistoryFacade {
 
+	private static final String HISTORIZED_POSTFIX = "_HIST";
 	private static Map timeOffsetsMap = new IdentityHashMap();
 
     protected HistoryFacade() {
@@ -121,7 +122,7 @@
             long endTime = System.currentTimeMillis();
             long jvmTime = (endTime - startTime) / 2 + startTime;
             long offset = databaseTime.getTime() - jvmTime;
-            timeOffsetsMap.put(rootSession, new Long(offset));
+            timeOffsetsMap.put(rootSession, offset);
             return jvmTime + offset;
         }
     }
@@ -133,14 +134,14 @@
      * the descriptors.
      */
     @SuppressWarnings("unchecked")
-	public static void generateHistoricalTableDefinitions(TableCreator creator, Session session) {
+	public static void generateHistoricalTableDefinitions(TableCreator creator, Session session) {	//NOSONAR
 
         // First add all table definitions to a hashtable.
         Map<String, TableDefinition> tableDefinitions = new HashMap(creator.getTableDefinitions().size());
         for (TableDefinition def : creator.getTableDefinitions()) {
             tableDefinitions.put(def.getFullName(), def);
         }
-        Set<String> generatedTables = new HashSet<String>();
+        Set<String> generatedTables = new HashSet<>();
         for (ClassDescriptor descriptor : session.getDescriptors().values()) {
             HistoryPolicy policy = descriptor.getHistoryPolicy();
             if (policy != null) {
@@ -161,7 +162,7 @@
                     policy = m2mMapping.getHistoryPolicy();
                     if (policy != null) {
                         String name = m2mMapping.getRelationTableName();
-                        String histName = (String)policy.getHistoryTableNames().get(0);
+                        String histName = policy.getHistoryTableNames().get(0);
                         if (!generatedTables.contains(histName)) {
                             generatedTables.add(histName);
                             TableDefinition def = tableDefinitions.get(name);
@@ -173,7 +174,7 @@
                     policy = dcMapping.getHistoryPolicy();
                     if (policy != null) {
                         String name = dcMapping.getReferenceTableName();
-                        String histName = (String)policy.getHistoryTableNames().get(0);
+                        String histName = policy.getHistoryTableNames().get(0);
                         if (!generatedTables.contains(histName)) {
                             generatedTables.add(histName);
                             TableDefinition def = tableDefinitions.get(name);
@@ -212,9 +213,9 @@
                 String name = table.getQualifiedNameDelimited(platform);
                 String historicalName;
                 if(table.shouldUseDelimiters()) {
-                    historicalName = name.substring(0, name.length() - 1) + "_HIST" + Helper.getDefaultEndDatabaseDelimiter();
+                    historicalName = name.substring(0, name.length() - 1) + HISTORIZED_POSTFIX + Helper.getDefaultEndDatabaseDelimiter();
                 } else {
-                    historicalName = name + "_HIST";
+                    historicalName = name + HISTORIZED_POSTFIX;
                 }
                 policy.addHistoryTableName(name, historicalName);
             }
@@ -228,14 +229,14 @@
                     ManyToManyMapping m2mMapping = (ManyToManyMapping)mapping;
                     policy = (HistoryPolicy)basePolicy.clone();
                     policy.addHistoryTableName(m2mMapping.getRelationTableName() +
-                                               "_HIST");
+                                               HISTORIZED_POSTFIX);
                     m2mMapping.setHistoryPolicy(policy);
                 } else if (mapping instanceof DirectCollectionMapping) {
                     DirectCollectionMapping dcMapping =
                         (DirectCollectionMapping)mapping;
                     policy = (HistoryPolicy)basePolicy.clone();
                     policy.addHistoryTableName(dcMapping.getReferenceTableName() +
-                                               "_HIST");
+                                               HISTORIZED_POSTFIX);
                     dcMapping.setHistoryPolicy(policy);
                 }
             }
diff --git a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/listener/EntityInfoListener.java b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/listener/EntityInfoListener.java
index 9b50ed6..8983910 100644
--- a/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/listener/EntityInfoListener.java
+++ b/org.eclipse.osbp.jpa.services/src/org/eclipse/osbp/jpa/services/listener/EntityInfoListener.java
@@ -27,6 +27,9 @@
 			String user = (String) session.get("userId");
 			BeanUtils.setUpdateUser(bean, user);
 			BeanUtils.setUpdateAt(bean, new Date());
+			if(BeanUtils.isHistorized(bean.getClass())) {
+				System.out.println("hist");
+			}
 		}
 	}
 }