/*
 * Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the
 * @author tags. See the copyright.txt file in the distribution for a full
 * listing of individual contributors.
 * 
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This software 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 Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */
package org.zanata.model;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.PostPersist;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@MappedSuperclass
public class ModelEntityBase implements Serializable, HashableState
{

   private static final long serialVersionUID = -6139220551322868743L;
   protected Long id;
   protected Date creationDate;
   protected Date lastChanged;

   protected Integer versionNum;

   @Id
   @GeneratedValue
   public Long getId()
   {
      return id;
   }

   protected void setId(Long id)
   {
      this.id = id;
   }

   @Version
   @Column(nullable = false)
   public Integer getVersionNum()
   {
      return versionNum;
   }

   public void setVersionNum(Integer versionNum)
   {
      this.versionNum = versionNum;
   }

   @Temporal(TemporalType.TIMESTAMP)
   @Column(nullable = false)
   public Date getCreationDate()
   {
      return creationDate;
   }

   public void setCreationDate(Date creationDate)
   {
      this.creationDate = creationDate;
   }

   @Temporal(TemporalType.TIMESTAMP)
   @Column(nullable = false)
   public Date getLastChanged()
   {
      return lastChanged;
   }

   public void setLastChanged(Date lastChanged)
   {
      this.lastChanged = lastChanged;
   }

   @SuppressWarnings("unused")
   @PrePersist
   private void onPersist()
   {
      creationDate = new Date();
      lastChanged = creationDate;
   }
   
   @SuppressWarnings("unused")
   @PreRemove
   private void onRemove()
   {
      if (logPersistence())
      {
         Logger log = LoggerFactory.getLogger(getClass());
         log.info("remove entity: {}", this);
      }
   }

   @SuppressWarnings("unused")
   @PreUpdate
   private void onUpdate()
   {
      lastChanged = new Date();
   }

   @SuppressWarnings("unused")
   @PostPersist
   private void postPersist()
   {
      if (logPersistence())
      {
         Logger log = LoggerFactory.getLogger(getClass());
         log.info("persist entity: {}", this);
      }
   }

   @Override
   public int hashCode()
   {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((creationDate == null) ? 0 : creationDate.hashCode());
      result = prime * result + ((id == null) ? 0 : id.hashCode());
      result = prime * result + ((lastChanged == null) ? 0 : lastChanged.hashCode());
      return result;
   }

   @Override
   public boolean equals(Object obj)
   {
      if (this == obj)
         return true;
      if (obj == null)
         return false;
      if (getClass() != obj.getClass())
         return false;
      ModelEntityBase other = (ModelEntityBase) obj;
      if (creationDate == null)
      {
         if (other.creationDate != null)
            return false;
      }
      else if (!creationDate.equals(other.creationDate))
         return false;
      if (id == null)
      {
         if (other.id != null)
            return false;
      }
      else if (!id.equals(other.id))
         return false;
      if (lastChanged == null)
      {
         if (other.lastChanged != null)
            return false;
      }
      else if (!lastChanged.equals(other.lastChanged))
         return false;
      return true;
   }

   @Override
   public String toString()
   {
      return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "[id=" + id + ",versionNum=" + versionNum + "]";
   }

   protected boolean logPersistence()
   {
      return true;
   }

   @Override
   public void writeHashState(ByteArrayOutputStream buff) throws IOException
   {
      buff.write(versionNum.byteValue());
   }
}

@@ -2766,35 +2766,128 @@
     
-creationDate = new Date();%0A
+if (creationDate != null)%0A      %7B%0A         creationDate = new Date();%0A      %7D%0A      if (lastChanged != null)%0A      %7B%0A   
     
@@ -2920,17 +2920,22 @@
 te;%0A
+      %7D%0A
    %7D%0A
-   
 %0A
+
    @
@@ -2966,24 +2966,26 @@
 %22)%0A   @P
-reRemove
+ostPersist
 %0A   priv
@@ -2997,16 +2997,19 @@
 oid 
-onRemove
+postPersist
 ()%0A 
@@ -3130,14 +3130,15 @@
 fo(%22
-remove
+persist
  ent
@@ -3315,34 +3315,32 @@
 used%22)%0A   @P
-ostPersist
+reRemove
 %0A   private 
@@ -3340,35 +3340,32 @@
 rivate void 
-postPersist
+onRemove
 ()%0A   %7B%0A    
@@ -3466,39 +3466,38 @@
       log.info(%22
-persist
+remove
  entity: %7B%7D%22, th

Allow creationDate and lastChanged to be set explicitly