All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.mihosoft.vmf.vmftext.grammar.impl.CodeLocationImpl Maven / Gradle / Ivy


package eu.mihosoft.vmf.vmftext.grammar.impl;

// vmf imports
// import eu.mihosoft.vmf.runtime.core.*;
// import eu.mihosoft.vmf.runtime.core.internal.*;
import eu.mihosoft.vcollections.*;
import eu.mihosoft.vmf.vmftext.grammar.*;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.util.Objects;
import java.util.Arrays;

// property types imports

// implementation

/**
 * An implementation of the immutable model object {@code eu.mihosoft.vmf.vmftext.grammar.CodeLocation}.
 */
@SuppressWarnings("deprecation")
public class CodeLocationImpl implements CodeLocation, eu.mihosoft.vmf.runtime.core.VObject, eu.mihosoft.vmf.runtime.core.internal.VObjectInternal, VCloneableInternal {

  // --------------------------------------------------------------------
  // --- declaration of member variables
  // --------------------------------------------------------------------


  /*package private*/ int charPosInLine;
  /*package private*/ int index;
  /*package private*/ int line;


// --------------------------------------------------------------------
// --- declaration of delegation variables
// --------------------------------------------------------------------


  // referenced by
  private final VList referencedBy = VList.newInstance(new java.util.ArrayList<>());
  // references
  private final VList references = VList.newInstance(new java.util.ArrayList<>());

  // --------------------------------------------------------------------
  // --- private constructor
  // --------------------------------------------------------------------

  private CodeLocationImpl() {
    // ...
  }

  // --------------------------------------------------------------------
  // --- public getter methods for accessing properties
  // --------------------------------------------------------------------

  @Override
  public int getCharPosInLine() {
    return this.charPosInLine;
  }
  @Override
  public int getIndex() {
    return this.index;
  }
  @Override
  public int getLine() {
    return this.line;
  }

  // --------------------------------------------------------------------
  // --- Object methods (equals(), toString() etc.)
  // --------------------------------------------------------------------


  // --------------------------- BEGIN TO_STRING -----------------------------
  @Override
  public String toString() {

    boolean entry = _vmf_getThreadLocalToString().get().isEmpty();
    try {
        // test if "this" has been seen before
        // implementation based on http://stackoverflow.com/a/11300376/1493549
        boolean isImmutable = (this instanceof eu.mihosoft.vmf.runtime.core.Immutable);
        if (!isImmutable && _vmf_getThreadLocalToString().get().containsKey(this)) {
          return "{skipping recursion}";
        } else {
          if(!isImmutable) {
            _vmf_getThreadLocalToString().get().put(this, null);
          }
          entry = true;
        }
        return "{\"@type\":\"CodeLocation\"" +
        ", \"charPosInLine\": \"" + this.charPosInLine + "\"" +
          ", \"index\": \"" + this.index + "\"" +
          ", \"line\": \"" + this.line + "\"" +
           "}";
    } finally {
        if (entry) {
            _vmf_getThreadLocalToString().get().clear();
            _vmf_fToStringChecker = null;
        }
    }
  }

  private ThreadLocal> _vmf_getThreadLocalToString() {
    if (_vmf_fToStringChecker==null) {
      _vmf_fToStringChecker = ThreadLocal.withInitial(
        () -> new java.util.IdentityHashMap<>());
    }

    return _vmf_fToStringChecker;
  }

  private ThreadLocal> _vmf_fToStringChecker;

  // end toString()
  // ---------------------------- END TO_STRING ------------------------------


  // --------------------------- BEGIN EQUALITY -----------------------------
  @Override
  public boolean equals(Object o) {

    boolean entry = _vmf_getThreadLocalEquals().get().isEmpty();
    try {
      // test if the object pair (this,o) has been checked before
      boolean isImmutable = (o instanceof eu.mihosoft.vmf.runtime.core.Immutable);
      if (!isImmutable && _vmf_getThreadLocalEquals().get().containsKey(new EqualsPair(this, o))) {
        // This pair has been seen before. That's why we return true now.
        // If this pair wasn't equal, we wouldn't need to do a second
        // comparison. Returning 'true' is equivalent to ignoring this
        // particular test in the calling 'equals()' method.
        return true;
      } else {
        if(!isImmutable) {
          _vmf_getThreadLocalEquals().get().put(new EqualsPair(this, o), null);
        }
        entry = true;
      }

      if (o==null) return false;
      else if (this==o) return true;


      // -- try our interface/implementation --

      // perform the actual comparison for each property
      if (o instanceof CodeLocationImpl) {
        CodeLocationImpl other = (CodeLocationImpl) o;
        return           _vmf_equals(this.charPosInLine, other.charPosInLine) &&
          _vmf_equals(this.index, other.index) &&
          _vmf_equals(this.line, other.line);
      }

      // -- try every implementation that implements our interface --

      // no implementation matched. we end the comparison.
      return false;
    } finally {
      if (entry) {
          _vmf_getThreadLocalEquals().get().clear();
          _vmf_fEqualsChecker = null;
      }
    }
  } // end equals()

  private static boolean _vmf_equals(Object o1, Object o2) {
    boolean oneAndOnlyOneIsNull = (o1 == null) != (o2 == null);
    boolean collectionType = o1 instanceof VList || o2 instanceof VList;

    // since we support lazy initialization for collections,
    // uninitialized empty collection values are defined as equal to null
    // otherwise we would have to initialize these values, which would then
    // neutralize or even negate the positive effect of lazy initialization
    if(oneAndOnlyOneIsNull && collectionType) {
      if(o1==null) {
        return ((VList)o2).isEmpty();
      } else {
        return ((VList)o1).isEmpty();
      }
    } else {
      return Objects.equals(o1,o2);
    }
  }

  @Override
  public int hashCode() {
      boolean entry = _vmf_getThreadLocalHashCode().get().isEmpty();
      try {
          // test if "this class" has been seen before
          //
          // WARNING we use `System.identityHashCode(this)` to prevent recursive
          // hashCode() calls before we do the actual test. This would eliminate
          // the effect of the thread-local map
          if (_vmf_getThreadLocalHashCode().get().containsKey(System.identityHashCode(this))) {
            return 0; // already visited
          } else {
            _vmf_getThreadLocalHashCode().get().put(System.identityHashCode(this), null);
            int value = _vmf_deepHashCode(
            this.charPosInLine,            this.index,            this.line        );
            entry = true;
            return value;
          }

      } finally {
          if (entry) {
              _vmf_getThreadLocalHashCode().get().clear();
              _vmf_fHashCodeChecker = null;
          }
      }

  } // end hashCode()

  // fixes 'array discovery problems' with the 'Objects.hash(...)' method
  // see http://stackoverflow.com/questions/30385018/how-to-use-java-7-objects-hash-with-arrays
  private int _vmf_deepHashCode(Object... fields) {
      // WARNING we are not allowed to pass arrays that contain itself
      //         or are contained in nested arrays
      return Arrays.deepHashCode(fields);
  } // end _vmf_deepHashCode()

  /**
   * The purpose of this class is to store a pair of objects used for equals().
   * This class's equals() method checks equality by object identity. Same
   * for hashCode() which uses identity hashes of 'first' and 'second' to
   * compute the hash.
   *
   * This class can be used in conjunction with a regular HashMap to get
   * similar results to an IdentityHashMap, except that in this case identity
   * pairs can be used. And we don't have to use a map implementation that is
   * deliberately broken by design.
   */
  private static class EqualsPair {

      final Object first;
      final Object second;

      public EqualsPair(Object first, Object second) {
          this.first = first;
          this.second = second;
      }

      @Override
      public int hashCode() {
          return Objects.hash(System.identityHashCode(first),
                  System.identityHashCode(second));
      }

      @Override
      public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final EqualsPair other = (EqualsPair) obj;
        if (this.first!=other.first) {
            return false;
        }
        if (this.second!=other.second) {
            return false;
        }
        return true;
      }
  }

  private ThreadLocal> _vmf_getThreadLocalEquals() {
    if (_vmf_fEqualsChecker==null) {
      _vmf_fEqualsChecker = ThreadLocal.withInitial(
        () -> new java.util.HashMap<>());
    }

    return _vmf_fEqualsChecker;
  }

  private ThreadLocal> _vmf_getThreadLocalHashCode() {
    if (_vmf_fHashCodeChecker==null) {
      _vmf_fHashCodeChecker = ThreadLocal.withInitial(
        () -> new java.util.HashMap<>());
    }

    return _vmf_fHashCodeChecker;
  }

  private ThreadLocal> _vmf_fEqualsChecker;


  private ThreadLocal> _vmf_fHashCodeChecker;
  // ---------------------------- END EQUALITY ------------------------------

  public CodeLocation clone() {
    // we don't need to perform actual cloning since this is an
    // immutable type
    return this;
  }


// --------------------------------------------------------------------
// --- Builder methods
// --------------------------------------------------------------------

public static class BuilderImpl implements CodeLocation.Builder {

  private int charPosInLine;
  private int index;
  private int line;

  private boolean appendCollections = true;

  public BuilderImpl() {}

    public CodeLocation.Builder withCharPosInLine(int charPosInLine) {
      this.charPosInLine = charPosInLine;
      return this;
    }
    public CodeLocation.Builder withIndex(int index) {
      this.index = index;
      return this;
    }
    public CodeLocation.Builder withLine(int line) {
      this.line = line;
      return this;
    }

  public Builder appendCollections(boolean value) {
    this.appendCollections = value;
    return this;
  }

  public CodeLocation build() {
    CodeLocationImpl result = new CodeLocationImpl();
    result.charPosInLine = this.charPosInLine;
    result.index = this.index;
    result.line = this.line;
    return result;
  }

  public Builder applyFrom(CodeLocation o) {
      this.charPosInLine = o.getCharPosInLine();
      this.index = o.getIndex();
      this.line = o.getLine();

    return this;
  }
} // end class BuilderImpl


// --------------------------------------------------------------------
// --- declaration of delegation methods
// --------------------------------------------------------------------


  // --------------------------------------------------------------------
  // --- Utility methods
  // --------------------------------------------------------------------

  @Override
  public void addPropertyChangeListener(PropertyChangeListener l) {
      // don't do anything. immutable types don't publish change events
  }
  @Override
  public void removePropertyChangeListener(PropertyChangeListener l) {
      // don't do anything. immutable types don't publish change events
  }

  private boolean _vmf_hasListeners() {
      return false;
  }

  private void _vmf_firePropertyChangeIfListenersArePresent() {
     // don't do anything. immutable types don't publish change events
  }

  @Override
  public CodeLocation _vmf_deepCopy(
    java.util.IdentityHashMap identityMap) {
    return this;
  }

  @Override
  public CodeLocation _vmf_shallowCopy(
    java.util.IdentityHashMap identityMap) {
    return this;
  }

  // --------------------------------------------------------------------
  // --- Public VMF API
  // --------------------------------------------------------------------

 private eu.mihosoft.vmf.runtime.core.VMF vmf;

  @Override
  public eu.mihosoft.vmf.runtime.core.VMF vmf() {
    if(vmf==null) {
      vmf = new eu.mihosoft.vmf.runtime.core.VMF() {
        public eu.mihosoft.vmf.runtime.core.Content content() {
          return new eu.mihosoft.vmf.runtime.core.Content() {
            public eu.mihosoft.vmf.runtime.core.VIterator iterator() {
              return eu.mihosoft.vmf.runtime.core.VIterator.of(CodeLocationImpl.this);
            }
            public java.util.stream.Stream stream() {
              return eu.mihosoft.vmf.runtime.core.VIterator.of(CodeLocationImpl.this).asStream();
            }

            public eu.mihosoft.vmf.runtime.core.VIterator iterator(eu.mihosoft.vmf.runtime.core.VIterator.IterationStrategy strategy) {
              return eu.mihosoft.vmf.runtime.core.VIterator.of(CodeLocationImpl.this, strategy);
            }
            public java.util.stream.Stream stream(eu.mihosoft.vmf.runtime.core.VIterator.IterationStrategy strategy) {
              return eu.mihosoft.vmf.runtime.core.VIterator.of(CodeLocationImpl.this, strategy).asStream();
            }
            public  java.util.stream.Stream stream(Class type) {
              return stream().filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e);
            }
            public  java.util.stream.Stream stream(Class type, eu.mihosoft.vmf.runtime.core.VIterator.IterationStrategy strategy) {
              return stream(strategy).filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e);
            }
            public VList referencedBy() {
              return _vmf_referencedBy().asUnmodifiable();
            }
            public VList references() {
              return _vmf_references().asUnmodifiable();
            }

            @Override
            public CodeLocation deepCopy() {
              java.util.IdentityHashMap identityMap =
              new java.util.IdentityHashMap<>();
              return _vmf_deepCopy(identityMap);
            }

            @Override
            public CodeLocation shallowCopy() {
              // we don't copy anything since this is an immutable type
              return CodeLocationImpl.this;
              }
            };
          }

          private eu.mihosoft.vmf.runtime.core.internal.ChangesImpl changes;

          public eu.mihosoft.vmf.runtime.core.Changes changes() {
            if (changes==null) {
              changes = new eu.mihosoft.vmf.runtime.core.internal.ChangesImpl();
              changes.setModel(CodeLocationImpl.this);
            }

            return changes;
          }

          private eu.mihosoft.vmf.runtime.core.internal.ReflectImpl reflect;
    
          public eu.mihosoft.vmf.runtime.core.Reflect reflect() {
            if (reflect==null) {
              reflect = new eu.mihosoft.vmf.runtime.core.internal.ReflectImpl();
              reflect.setModel(CodeLocationImpl.this);
            }
    
            return reflect;
          }

        }; // end vmf
      } // end if null

      return vmf;
  }

  @Override
  public CodeLocation asReadOnly() {
    return this;
  }

  // --------------------------------------------------------------------
  // --- Reflection methods
  // --------------------------------------------------------------------

  // type id for improved reflection performance
  public static final int _VMF_TYPE_ID = 6;

  @Override
  public int _vmf_getTypeId() {
    return _VMF_TYPE_ID;
  }


  static final String[] _VMF_PROPERTY_NAMES = {
    "charPosInLine",
    "index",
    "line"
  };

  static final String[] _VMF_PROPERTY_TYPE_NAMES = {
    "int", // type id -1
    "int", // type id -1
    "int"  // type id -1
  };

  static final int[] _VMF_PROPERTY_TYPES = {
       -1, // type int
       -1, // type int
       -1  // type int
  };


  /**
   * - indices of model objects as properties
   * - parents, i.e., containers are skipped
   * - only indices of reference properties and contained elements, i.e.,
   *   children are listed here
   */
  static final int[] _VMF_PROPERTIES_WITH_MODEL_TYPES_INDICES = {
  };

  /**
   * - indices of lists that contain model objects as elements
   */
  static final int[] _VMF_PROPERTIES_WITH_MODEL_ELEMENT_TYPES_INDICES = {
  };

  /**
   * - indices of model objects as properties and model objects as
   *   elements of lists
   * - parents, i.e., containers are skipped
   * - only indices of reference properties and contained elements, i.e.,
   *   children are listed here
   */
  static final int[] _VMF_PROPERTIES_WITH_MODEL_TYPE_OR_ELEMENT_TYPES_INDICES = {
  };

  /**
   * - indices of model children
   * - parents, i.e., containers and pure references are skipped
   * - only indices of contained elements, i.e.,
   *   children are listed here
   */
  static final int[] _VMF_CHILDREN_INDICES = {
  };

  @Override
  public String[] _vmf_getPropertyNames() {
    return _VMF_PROPERTY_NAMES;
  }

  @Override
  public int[] _vmf_getPropertyTypes() {
    return _VMF_PROPERTY_TYPES;
  }

  @Override
  public String[] _vmf_getPropertyTypeNames() {
    return _VMF_PROPERTY_TYPE_NAMES;
  }

  @Override
  public int[] _vmf_getIndicesOfPropertiesWithModelTypes() {
    return _VMF_PROPERTIES_WITH_MODEL_TYPES_INDICES;
  }

  @Override
  public int[] _vmf_getIndicesOfPropertiesWithModelElementTypes() {
    return _VMF_PROPERTIES_WITH_MODEL_ELEMENT_TYPES_INDICES;
  }

  @Override
  public int[] _vmf_getIndicesOfPropertiesWithModelTypeOrElementTypes() {
    return _VMF_PROPERTIES_WITH_MODEL_TYPE_OR_ELEMENT_TYPES_INDICES;
  }

  @Override
  public int[] _vmf_getChildrenIndices() {
    return _VMF_CHILDREN_INDICES;
  }

  @Override
  public Object _vmf_getPropertyValueById(int propertyId) {

    switch(propertyId) {
      case 0:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getCharPosInLine();
      case 1:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getIndex();
      case 2:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getLine();
    }

    return null;
  }

  @Override
  public int _vmf_getPropertyIdByName(String propertyName) {
    switch(propertyName) {
      case "charPosInLine":
        return 0;
      case "index":
        return 1;
      case "line":
        return 2;
      default:
        return -1;
    } // end switch
  }


  @Override
  public Object _vmf_getDefaultValueById(int propertyId) {

    switch(propertyId) {
      case 0:
        Object __vmf_default_value_tmpCharPosInLine = _VMF_DEFAULT_VALUES[0];
        if(__vmf_default_value_tmpCharPosInLine==null) {
            return
             0;
        } else {
            return __vmf_default_value_tmpCharPosInLine;
        }    

      case 1:
        Object __vmf_default_value_tmpIndex = _VMF_DEFAULT_VALUES[1];
        if(__vmf_default_value_tmpIndex==null) {
            return
             0;
        } else {
            return __vmf_default_value_tmpIndex;
        }    

      case 2:
        Object __vmf_default_value_tmpLine = _VMF_DEFAULT_VALUES[2];
        if(__vmf_default_value_tmpLine==null) {
            return
             0;
        } else {
            return __vmf_default_value_tmpLine;
        }    

    } // end switch

    return null;
  }

  @Override
  public void _vmf_setDefaultValueById(int propertyId, Object defaultValue) {


  }

  @Override
  public boolean _vmf_isSetById(int propertyId) {
    return !java.util.Objects.equals(_vmf_getDefaultValueById(propertyId), _vmf_getPropertyValueById(propertyId));
  }


  final Object[] _VMF_DEFAULT_VALUES = {
    null, // type charPosInLine   
    null, // type index   
    null  // type line   
  };

  // --------------------------------------------------------------------
  // --- Id related methods
  // --------------------------------------------------------------------

  // id management is currently not part of VMF (TODO how should we support this?)

  // --------------------------------------------------------------------
  // --- Reference methods
  // --------------------------------------------------------------------

  @Override
  public VList _vmf_referencedBy() { return this.referencedBy;}
  @Override
  public VList _vmf_references() { return this.references;}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy