// Path: src/main/java/org/jacis/exception/ReadOnlyModeNotSupportedException.java
// @JacisApi
// public class ReadOnlyModeNotSupportedException extends IllegalStateException {
// 
//   private static final long serialVersionUID = 1L;
// 
//   public ReadOnlyModeNotSupportedException(String s) {
//     super(s);
//   }
// }
// 
// Path: src/main/java/org/jacis/plugin/objectadapter/JacisObjectAdapter.java
// @JacisApi
// public interface JacisObjectAdapter<TV, CV> {
// 
//   /**
//    * Clone a committed version of the object into the transactional view.
//    * Note that modifications ib the returned transactional view must not influence the committed version of the object.
//    *
//    * @param value Committed version of the object.
//    * @return A transactional view for the passed object.
//    */
//   TV cloneCommitted2WritableTxView(CV value);
// 
//   /**
//    * Clone back a transactional view of the object into the committed version of the object.
//    * The returned committed version will replace the previous one in the store of the committed values.
//    *
//    * @param value A transactional view for the passed object.
//    * @return Committed version of the object.
//    */
//   CV cloneTxView2Committed(TV value);
// 
//   /**
//    * Clone a committed version of the object into a read only transactional view.
//    * Modifications of the read only view must not be possible (lead to an exception).
//    * As an optimization it is allowed to skip a real cloning here since the returned object is guaranteed to be read only.
//    * Note that a difference using read only views where cloning is skipped is that a repeated read of the same object
//    * may return different versions of the object if another transaction committed a newer version between both reads.
//    * 
//    * @param value Committed version of the object.
//    * @return A read only transactional view for the passed object.
//    */
//   TV cloneCommitted2ReadOnlyTxView(CV value);
// 
//   /**
//    * Convert a transactional view of an object into a read only representation of this object.
//    * Modifications of the read only view must not be possible (lead to an exception).
//    * 
//    * @param value A transactional view for the passed object.
//    * @return A read only transactional view for the passed object.
//    */
//   TV cloneTxView2ReadOnlyTxView(TV value);
// 
// }
// 
// Path: src/main/java/org/jacis/plugin/readonly/DefaultJacisStoreEntryReadOnlyModeAdapter.java
// public class DefaultJacisStoreEntryReadOnlyModeAdapter<V> implements JacisStoreEntryReadOnlyModeAdapter<V> {
// 
//   @Override
//   public boolean isApplicableTo(V value) {
//     return value instanceof JacisReadonlyModeSupport;
//   }
// 
//   @Override
//   public boolean isReadOnly(V value) {
//     return ((JacisReadonlyModeSupport) value).isReadOnly();
//   }
// 
//   @Override
//   public V switchToReadOnlyMode(V value) {
//     ((JacisReadonlyModeSupport) value).switchToReadOnlyMode();
//     return value;
//   }
// 
//   @Override
//   public V switchToReadWriteMode(V value) {
//     ((JacisReadonlyModeSupport) value).switchToReadWriteMode();
//     return value;
//   }
// 
//   @Override
//   public String toString() {
//     return getClass().getSimpleName();
//   }
// }
// 
// Path: src/main/java/org/jacis/plugin/readonly/JacisStoreEntryReadOnlyModeAdapter.java
// @JacisApi
// public interface JacisStoreEntryReadOnlyModeAdapter<V> {
// 
//   /**
//    * Returns if this adapter can switch the read / write mode for the passed object
//    *
//    * @param value The object to check.
//    * @return if this adapter can switch the read / write mode for the passed object
//    */
//   boolean isApplicableTo(V value);
// 
//   /**
//    * Returns if the passed object is in read-only mode
//    *
//    * @param value The object to check.
//    * @return if the passed object is in read-only mode
//    */
//   boolean isReadOnly(V value);
// 
//   /**
//    * Switch the read / write mode for the passed object to read-only mode
//    * Note that the calling methods will work with the returned value.
//    * Therefore the implementation of the method may return another instance than the passed (e.g. a proxy).
//    *
//    * @param value The object to switch to read-only mode
//    * @return the object with the switched mode.
//    */
//   V switchToReadOnlyMode(V value);
// 
//   /**
//    * Switch the read / write mode for the passed object to read-write mode
//    * Note that the calling methods will work with the returned value.
//    * Therefore the implementation of the method may return another instance than the passed (e.g. a proxy).
//    *
//    * @param value The object to switch to read-write mode
//    * @return the object with the switched mode.
//    */
//   V switchToReadWriteMode(V value);
// 
// }


import org.jacis.JacisApi;
import org.jacis.exception.ReadOnlyModeNotSupportedException;
import org.jacis.plugin.objectadapter.JacisObjectAdapter;
import org.jacis.plugin.readonly.DefaultJacisStoreEntryReadOnlyModeAdapter;
import org.jacis.plugin.readonly.JacisStoreEntryReadOnlyModeAdapter;

  public V cloneCommitted2ReadOnlyTxView(V value) {
    if (value == null) {
      return null;
    }
    checkReadOnlyModeSupported(value);
    V clone;
    if (readOnlyModeAdapter == null || !readOnlyModeAdapter.isApplicableTo(value)) {
      clone = cloneValue(value);
    } else {
      clone = value; // for read only objects we do not clone the returned object. -> skip call of: cloneValue(value);
    }
    return clone;
  }

  @Override
  public V cloneTxView2ReadOnlyTxView(V value) {
    if (value == null) {
      return null;
    }
    if (readOnlyModeAdapter != null && readOnlyModeAdapter.isApplicableTo(value)) {
      if (readOnlyModeAdapter.isReadOnly(value)) {
        return value;
      } else {
        return readOnlyModeAdapter.switchToReadOnlyMode(cloneValue(value));
      }
    } else {
      return cloneValue(value);
    }
  }


// Path: src/main/java/org/jacis/exception/ReadOnlyModeNotSupportedException.java
// @JacisApi
// public class ReadOnlyModeNotSupportedException extends IllegalStateException {
// 
//   private static final long serialVersionUID = 1L;
// 
//   public ReadOnlyModeNotSupportedException(String s) {
//     super(s);
//   }
// }
// 
// Path: src/main/java/org/jacis/plugin/objectadapter/JacisObjectAdapter.java
// @JacisApi
// public interface JacisObjectAdapter<TV, CV> {
// 
//   /**
//    * Clone a committed version of the object into the transactional view.
//    * Note that modifications ib the returned transactional view must not influence the committed version of the object.
//    *
//    * @param value Committed version of the object.
//    * @return A transactional view for the passed object.
//    */
//   TV cloneCommitted2WritableTxView(CV value);
// 
//   /**
//    * Clone back a transactional view of the object into the committed version of the object.
//    * The returned committed version will replace the previous one in the store of the committed values.
//    *
//    * @param value A transactional view for the passed object.
//    * @return Committed version of the object.
//    */
//   CV cloneTxView2Committed(TV value);
// 
//   /**
//    * Clone a committed version of the object into a read only transactional view.
//    * Modifications of the read only view must not be possible (lead to an exception).
//    * As an optimization it is allowed to skip a real cloning here since the returned object is guaranteed to be read only.
//    * Note that a difference using read only views where cloning is skipped is that a repeated read of the same object
//    * may return different versions of the object if another transaction committed a newer version between both reads.
//    * 
//    * @param value Committed version of the object.
//    * @return A read only transactional view for the passed object.
//    */
//   TV cloneCommitted2ReadOnlyTxView(CV value);
// 
//   /**
//    * Convert a transactional view of an object into a read only representation of this object.
//    * Modifications of the read only view must not be possible (lead to an exception).
//    * 
//    * @param value A transactional view for the passed object.
//    * @return A read only transactional view for the passed object.
//    */
//   TV cloneTxView2ReadOnlyTxView(TV value);
// 
// }
// 
// Path: src/main/java/org/jacis/plugin/readonly/DefaultJacisStoreEntryReadOnlyModeAdapter.java
// public class DefaultJacisStoreEntryReadOnlyModeAdapter<V> implements JacisStoreEntryReadOnlyModeAdapter<V> {
// 
//   @Override
//   public boolean isApplicableTo(V value) {
//     return value instanceof JacisReadonlyModeSupport;
//   }
// 
//   @Override
//   public boolean isReadOnly(V value) {
//     return ((JacisReadonlyModeSupport) value).isReadOnly();
//   }
// 
//   @Override
//   public V switchToReadOnlyMode(V value) {
//     ((JacisReadonlyModeSupport) value).switchToReadOnlyMode();
//     return value;
//   }
// 
//   @Override
//   public V switchToReadWriteMode(V value) {
//     ((JacisReadonlyModeSupport) value).switchToReadWriteMode();
//     return value;
//   }
// 
//   @Override
//   public String toString() {
//     return getClass().getSimpleName();
//   }
// }
// 
// Path: src/main/java/org/jacis/plugin/readonly/JacisStoreEntryReadOnlyModeAdapter.java
// @JacisApi
// public interface JacisStoreEntryReadOnlyModeAdapter<V> {
// 
//   /**
//    * Returns if this adapter can switch the read / write mode for the passed object
//    *
//    * @param value The object to check.
//    * @return if this adapter can switch the read / write mode for the passed object
//    */
//   boolean isApplicableTo(V value);
// 
//   /**
//    * Returns if the passed object is in read-only mode
//    *
//    * @param value The object to check.
//    * @return if the passed object is in read-only mode
//    */
//   boolean isReadOnly(V value);
// 
//   /**
//    * Switch the read / write mode for the passed object to read-only mode
//    * Note that the calling methods will work with the returned value.
//    * Therefore the implementation of the method may return another instance than the passed (e.g. a proxy).
//    *
//    * @param value The object to switch to read-only mode
//    * @return the object with the switched mode.
//    */
//   V switchToReadOnlyMode(V value);
// 
//   /**
//    * Switch the read / write mode for the passed object to read-write mode
//    * Note that the calling methods will work with the returned value.
//    * Therefore the implementation of the method may return another instance than the passed (e.g. a proxy).
//    *
//    * @param value The object to switch to read-write mode
//    * @return the object with the switched mode.
//    */
//   V switchToReadWriteMode(V value);
// 
// }


// Path: src/main/java/org/jacis/plugin/objectadapter/cloning/AbstractJacisCloningObjectAdapter.java
import org.jacis.JacisApi;
import org.jacis.exception.ReadOnlyModeNotSupportedException;
import org.jacis.plugin.objectadapter.JacisObjectAdapter;
import org.jacis.plugin.readonly.DefaultJacisStoreEntryReadOnlyModeAdapter;
import org.jacis.plugin.readonly.JacisStoreEntryReadOnlyModeAdapter;

  public V cloneCommitted2ReadOnlyTxView(V value) {
    if (value == null) {
      return null;
    }
    checkReadOnlyModeSupported(value);
    V clone;
    if (readOnlyModeAdapter == null || !readOnlyModeAdapter.isApplicableTo(value)) {
      clone = cloneValue(value);
    } else {
      clone = value; // for read only objects we do not clone the returned object. -> skip call of: cloneValue(value);
    }
    return clone;
  }

  @Override
  public V cloneTxView2ReadOnlyTxView(V value) {
    if (value == null) {
      return null;
    }
    if (readOnlyModeAdapter != null && readOnlyModeAdapter.isApplicableTo(value)) {
      if (readOnlyModeAdapter.isReadOnly(value)) {
        return value;
      } else {
        return readOnlyModeAdapter.switchToReadOnlyMode(cloneValue(value));
      }
    } else {
      return cloneValue(value);
    }
  }


  private void checkReadOnlyModeSupported(V value) throws ReadOnlyModeNotSupportedException {
