package io.oasp.module.basic.common.api.to;
import net.sf.mmm.util.entity.api.GenericEntity;
import net.sf.mmm.util.entity.api.MutableRevisionedEntity;
import net.sf.mmm.util.entity.api.PersistenceEntity;
import net.sf.mmm.util.transferobject.api.TransferObject;
/**
* This is the abstract base class for an {@link TransferObject} that only contains data without relations. This is
* called <em>DTO</em> (data transfer object). Here data means properties that typically represent a
* {@link net.sf.mmm.util.lang.api.Datatype} and potentially for relations the ID (as {@link Long}). For actual
* relations you will use {@link AbstractCto CTO}s to express what set of entities to transfer, load, save, update, etc.
* without redundancies. It typically corresponds to an {@link net.sf.mmm.util.entity.api.GenericEntity entity}. For
* additional details and an example consult the.
*
*/
public abstract class AbstractEto extends AbstractTo implements MutableRevisionedEntity<Long> {
private static final long serialVersionUID = 1L;
/** @see #getId() */
private Long id;
/** @see #getModificationCounter() */
private int modificationCounter;
/** @see #getRevision() */
private Number revision;
/**
* @see #getModificationCounter()
*/
private transient GenericEntity<Long> persistentEntity;
/**
* The constructor.
*/
public AbstractEto() {
super();
this.revision = LATEST_REVISION;
}
/**
* {@inheritDoc}
*/
@Override
public Long getId() {
return this.id;
}
/**
* {@inheritDoc}
*/
@Override
public void setId(Long id) {
this.id = id;
}
/**
* {@inheritDoc}
*/
@Override
public int getModificationCounter() {
if (this.persistentEntity != null) {
// JPA implementations will update modification counter only after the transaction has been committed.
// Conversion will typically happen before and would result in the wrong (old) modification counter.
// Therefore we update the modification counter here (that has to be called before serialization takes
// place).
this.modificationCounter = this.persistentEntity.getModificationCounter();
}
return this.modificationCounter;
}
/**
* {@inheritDoc}
*/
@Override
public void setModificationCounter(int version) {
this.modificationCounter = version;
}
/**
* {@inheritDoc}
*/
@Override
public Number getRevision() {
return this.revision;
}
/**
* {@inheritDoc}
*/
@Override
public void setRevision(Number revision) {
this.revision = revision;
}
/**
* Method to extend {@link #toString()} logic.
*
* @param buffer is the {@link StringBuilder} where to {@link StringBuilder#append(Object) append} the string
* representation.
*/
@Override
protected void toString(StringBuilder buffer) {
super.toString(buffer);
if (this.id != null) {
buffer.append("[id=");
buffer.append(this.id);
buffer.append("]");
}
if (this.revision != null) {
buffer.append("[rev=");
buffer.append(this.revision);
buffer.append("]");
}
}
/**
* Inner class to grant access to internal {@link PersistenceEntity} reference of an {@link AbstractEto}. Shall only
* be used internally and never be external users.
*/
public static class PersistentEntityAccess {
/**
* Sets the internal {@link PersistenceEntity} reference of the given {@link AbstractEto}.
*
* @param <ID> is the generic type of the {@link GenericEntity#getId() ID}.
* @param eto is the {@link AbstractEto}.
* @param persistentEntity is the {@link PersistenceEntity}.
*/
protected <ID> void setPersistentEntity(AbstractEto eto, PersistenceEntity<Long> persistentEntity) {
assert ((eto.persistentEntity == null) || (persistentEntity == null));
eto.persistentEntity = persistentEntity;
}
}
}