package org.swellrt.model.generic;

import org.swellrt.model.ReadableType;

/**
 * Parent abstract class for data types stored in a SwellRT wavelet.
 *
 *
 * @author pablojan@gmail (Pablo Ojanguren)
 *
 */
public abstract class Type implements ReadableType {

  /**
   * Deserialize a Type instance based on its parent instance a its substrate
   * document or primitive value reference.
   *
   * @param parent Parent type instance.
   * @param ref a substrate document id or reference of a primitive value
   * @return
   */
  protected static Type deserialize(Type parent, String ref) {

    Type instance = null;

    if (ref.startsWith(StringType.PREFIX)) {
      instance = StringType.deserialize(parent, ref.substring(StringType.PREFIX.length() + 1));

    } else if (ref.startsWith(ListType.PREFIX)) {
      instance = ListType.deserialize(parent, ref);

    } else if (ref.startsWith(MapType.PREFIX)) {
      instance = MapType.deserialize(parent, ref);

    } else if (ref.startsWith(TextType.PREFIX)) {
      instance = TextType.deserialize(parent, ref);

    } else if (ref.startsWith(FileType.PREFIX)) {
      instance = FileType.deserialize(parent, ref.substring(FileType.PREFIX.length() + 1));

    } else if (ref.startsWith(NumberType.PREFIX)) {
      instance = NumberType.deserialize(parent, ref.substring(NumberType.PREFIX.length() + 1));

    } else if (ref.startsWith(BooleanType.PREFIX)) {
      instance = BooleanType.deserialize(parent, ref.substring(BooleanType.PREFIX.length() + 1));

    }

    return instance;
  }

  /** Attach a type instance to an existing substrate document. */
  protected abstract void attach(Type parent, String substrateDocumentIdOrValueIndex);


  /** Attach a type instance to a new substrate document. */
  protected abstract void attach(Type parent);

  /** Remove the backend document */
  protected abstract void deattach();


  /** Provide a initializer of this Type instance to be added in a ListType. */
  protected abstract ListElementInitializer getListElementInitializer();

  /** Get the document prefix used by documents of this type. */
  protected abstract String getPrefix();

  /** Check if the instance is supported by a document. */
  protected abstract boolean isAttached();

  /**
   * Provide a serialized Id for referencing the instance from others instance
   * of the model, by now just for MapType.
   */
  protected abstract String serialize();

  /**
   * Set type instance path. To be invoked after {@link #attach(Type)} by parent
   * object.
   */
  protected abstract void setPath(String path);

  /** Check if this instance is a container of primitive values. */
  protected abstract boolean hasValuesContainer();

  /** Get the container of primitive values of this instance. Null otherwise. */
  protected abstract ValuesContainer getValuesContainer();

  /** Get the reference string of the value stored in this instance. */
  protected abstract String getValueReference(Type value);

  /** Get the reference string of this value. For primitive values only. */
  protected Integer getValueRefefence() {
    return null;
  }

  /**
   * Used to mark updates of a primitive value in the container, in order to
   * generate a convinient sequence of DocOps.
   */
  protected void markValueUpdate(Type value) {
    // Default no-op
  }

  /** Get the path of this instance in a collaborative object model */
  public abstract String getPath();

  /** Return the Id of the Wave document storing this Type instance */
  public abstract String getDocumentId();

  /** Return the Model object managing this Type instance */
  public abstract Model getModel();

  /** Return this instance's Type as String */
  public abstract String getType();


//  private static native void jsLog(String m) /*-{
//    console.log(m);
//  }-*/;

  /** Log a trace message, don't use in prod. Only for low-level debug **/
  /*
  protected void trace(String m) {
    if (GWT.isScript()) {

      if (GWT.isProdMode()) {
        jsLog(m);
      } else {
        GWT.log(m);
      }

    } else {
      System.out.println(m);
    }
  }
  */

}

@@ -643,32 +643,38 @@
 tringType.PREFIX
+ + %22+%22
 )) %7B%0A      insta
@@ -796,32 +796,38 @@
 (ListType.PREFIX
+ + %22+%22
 )) %7B%0A      insta
@@ -904,32 +904,38 @@
 h(MapType.PREFIX
+ + %22+%22
 )) %7B%0A      insta
@@ -1012,32 +1012,38 @@
 (TextType.PREFIX
+ + %22+%22
 )) %7B%0A      insta
@@ -1121,32 +1121,38 @@
 (FileType.PREFIX
+ + %22+%22
 )) %7B%0A      insta
@@ -1272,32 +1272,38 @@
 umberType.PREFIX
+ + %22+%22
 )) %7B%0A      insta
@@ -1436,16 +1436,22 @@
 e.PREFIX
+ + %22+%22
 )) %7B%0A   
@@ -3764,19 +3764,20 @@
 pe();%0A%0A%0A
+  
 //
- 
  private
@@ -3821,13 +3821,12 @@
 *-%7B%0A
-// 
   
+//
  con
@@ -3838,19 +3838,20 @@
 log(m);%0A
+  
 //
- 
  %7D-*/;%0A%0A
@@ -3931,16 +3931,19 @@
 /%0A  /*%0A 
+  *
  protect
@@ -3967,20 +3967,16 @@
 ing m) %7B
-%0A   
  if (GWT
@@ -3993,18 +3993,16 @@
 )) %7B
-%0A%0A      if
+ if%0A   *
  (GW
@@ -4018,24 +4018,16 @@
 ode()) %7B
-%0A       
  jsLog(m
@@ -4028,22 +4028,16 @@
 sLog(m);
-%0A     
  %7D else 
@@ -4041,16 +4041,8 @@
 se %7B
-%0A       
  GWT
@@ -4053,21 +4053,10 @@
 (m);
-%0A      %7D%0A%0A  
  
+%7D
  %7D e
@@ -4064,18 +4064,17 @@
 se %7B%0A   
-  
+*
  System.
@@ -4092,19 +4092,14 @@
 (m);
-%0A  
  
+%7D
  %7D%0A 
- %7D%0A
   */

Handle swellrt model documents prefixes properly