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

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

The newest version!

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
import eu.mihosoft.vcollections.*;

// implementation

/**
 * An implementation of the model object {@code eu.mihosoft.vmf.vmftext.grammar.GrammarModel}.
 */
@SuppressWarnings("deprecation")
class GrammarModelImpl implements GrammarModel, eu.mihosoft.vmf.runtime.core.internal.VObjectInternalModifiable, VCloneableInternal {

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


  /*package private*/ eu.mihosoft.vcollections.VList customRules;
  /*package private*/ java.lang.String grammarName;
  /*package private*/ java.lang.String packageName;
  /*package private*/ eu.mihosoft.vcollections.VList ruleClasses;
  /*package private*/ eu.mihosoft.vmf.vmftext.grammar.TypeMappings typeMappings;


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

  private eu.mihosoft.vmf.vmftext.grammar.GetRootClassDelegate _vmf_delegate1;
  private eu.mihosoft.vmf.vmftext.grammar.RuleClassLookup _vmf_delegate2;
  private eu.mihosoft.vmf.vmftext.grammar.CheckRulesDelegate _vmf_delegate3;

  private PropertyChangeSupport propertyChanges;

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

  // --------------------------------------------------------------------
  // --- public constructors
  // --------------------------------------------------------------------

  public GrammarModelImpl() {

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


    if(_vmf_delegate3==null) {
      _vmf_delegate3 = new eu.mihosoft.vmf.vmftext.grammar.CheckRulesDelegate();
      _vmf_delegate3.setCaller(this);
    }

    _vmf_delegate3.onGrammarModelInstantiated();


// --------------------------------------------------------------------
// --- initialization of default values
// --------------------------------------------------------------------
    // property 0
    // -> no default value is present
    // property 1
    // -> no default value is present
    // property 2
    // -> no default value is present
    // property 3
    // -> no default value is present
    // property 4
    // -> no default value is present

  }

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


  @Override
  public eu.mihosoft.vcollections.VList getCustomRules() {

    if(this.customRules==null) {
      this.customRules = VList.newInstance(new java.util.ArrayList<>());

      this.customRules.addChangeListener((evt)-> {
            evt.added().elements().forEach((e)->{

                if(e==null) return;

                // remove element from previous collection
                // TODO use bulk operations if possible
                if(e.getModel()!=null) {
                  e.getModel().getCustomRules().remove(e);
                }

                
                try {
                  java.lang.reflect.Field field =
                    e.getClass().getDeclaredField("model");
                  field.setAccessible(true);
                  Object oldOpposite = field.get(e);
                  field.set(e, this);
                  // not generating change event (disableFireEventValue=true)
                } catch (Exception ex) {
                  java.util.logging.Logger.getLogger(
                     GrammarModelImpl.class.getName()).
                     log(java.util.logging.Level.SEVERE, null, ex);
                }



                if(e!=null && this!=null) {
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this)._vmf_references().add(e);
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)e)._vmf_referencedBy().add(this);
                }

            }); // end of evt.added()

            evt.removed().elements().forEach((e)->{
              if(e==null) return;
                
                try {
                  java.lang.reflect.Field field =
                    e.getClass().getDeclaredField("model");
                  field.setAccessible(true);
                  Object oldOpposite = field.get(e);
                  field.set(e, null);
                  // not generating change event (disableFireEventValue=true)
                } catch (Exception ex) {
                  java.util.logging.Logger.getLogger(
                     GrammarModelImpl.class.getName()).
                     log(java.util.logging.Level.SEVERE, null, ex);
                }




                if(e!=null && this!=null) {
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this)._vmf_references().add(e);
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)e)._vmf_referencedBy().add(this);
                }
            }); // end of evt.removed()
            
        }); // end of change listener

    } // end of "lazy init" if(this.customRules==null)

    return this.customRules;

    // return VContainmentUtil.asContainmentList(this.customRules, "model");
  } // end of eu.mihosoft.vcollections.VList getCustomRules()
  @Override
  public java.lang.String getGrammarName() {
    return this.grammarName;

  } // end of java.lang.String getGrammarName()
  @Override
  public java.lang.String getPackageName() {
    return this.packageName;

  } // end of java.lang.String getPackageName()
  @Override
  public eu.mihosoft.vcollections.VList getRuleClasses() {

    if(this.ruleClasses==null) {
      this.ruleClasses = VList.newInstance(new java.util.ArrayList<>());

      this.ruleClasses.addChangeListener((evt)-> {
            evt.added().elements().forEach((e)->{

                if(e==null) return;

                // remove element from previous collection
                // TODO use bulk operations if possible
                if(e.getModel()!=null) {
                  e.getModel().getRuleClasses().remove(e);
                }

                
                try {
                  java.lang.reflect.Field field =
                    e.getClass().getDeclaredField("model");
                  field.setAccessible(true);
                  Object oldOpposite = field.get(e);
                  field.set(e, this);
                  // not generating change event (disableFireEventValue=true)
                } catch (Exception ex) {
                  java.util.logging.Logger.getLogger(
                     GrammarModelImpl.class.getName()).
                     log(java.util.logging.Level.SEVERE, null, ex);
                }



                if(e!=null && this!=null) {
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this)._vmf_references().add(e);
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)e)._vmf_referencedBy().add(this);
                }

            }); // end of evt.added()

            evt.removed().elements().forEach((e)->{
              if(e==null) return;
                
                try {
                  java.lang.reflect.Field field =
                    e.getClass().getDeclaredField("model");
                  field.setAccessible(true);
                  Object oldOpposite = field.get(e);
                  field.set(e, null);
                  // not generating change event (disableFireEventValue=true)
                } catch (Exception ex) {
                  java.util.logging.Logger.getLogger(
                     GrammarModelImpl.class.getName()).
                     log(java.util.logging.Level.SEVERE, null, ex);
                }




                if(e!=null && this!=null) {
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this)._vmf_references().add(e);
                  ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)e)._vmf_referencedBy().add(this);
                }
            }); // end of evt.removed()
            
        }); // end of change listener

    } // end of "lazy init" if(this.ruleClasses==null)

    return this.ruleClasses;

    // return VContainmentUtil.asContainmentList(this.ruleClasses, "model");
  } // end of eu.mihosoft.vcollections.VList getRuleClasses()
  @Override
  public eu.mihosoft.vmf.vmftext.grammar.TypeMappings getTypeMappings() {
    return this.typeMappings;

  } // end of eu.mihosoft.vmf.vmftext.grammar.TypeMappings getTypeMappings()

  // --------------------------------------------------------------------
  // --- public setter methods for setting properties
  // --------------------------------------------------------------------


   @Override
   public void setGrammarName(java.lang.String grammarName) {

    // return early if identical value has been set
    if (this.grammarName == grammarName) {
      return;
    }

    // set the new value
    java.lang.String oldValue = this.grammarName;
    this.grammarName = grammarName;

    // fire property change event
    _vmf_firePropertyChangeIfListenersArePresent("grammarName", oldValue, this.grammarName);
 

  } // setterDeclaration (setter method)
     @Override
   public void setPackageName(java.lang.String packageName) {

    // return early if identical value has been set
    if (this.packageName == packageName) {
      return;
    }

    // set the new value
    java.lang.String oldValue = this.packageName;
    this.packageName = packageName;

    // fire property change event
    _vmf_firePropertyChangeIfListenersArePresent("packageName", oldValue, this.packageName);
 

  } // setterDeclaration (setter method)
      @Override
   public void setTypeMappings(eu.mihosoft.vmf.vmftext.grammar.TypeMappings typeMappings) {

    // return early if identical value has been set
    if (this.typeMappings == typeMappings) {
      return;
    }

    // set the new value
    eu.mihosoft.vmf.vmftext.grammar.TypeMappings oldValue = this.typeMappings;
    this.typeMappings = typeMappings;

    // fire property change event
    _vmf_firePropertyChangeIfListenersArePresent("typeMappings", oldValue, this.typeMappings);
      // if previous container is present then release containment relation
    if(oldValue!=null) {
      //((eu.mihosoft.vmf.vmftext.grammar.TypeMappingsImpl)oldValue)._vmf_setModelNoContainment(null);


      try {
        java.lang.reflect.Field field =
          oldValue.getClass().getDeclaredField("model");
        field.setAccessible(true);
        Object oldOpposite = field.get(oldValue);
        field.set(oldValue, null);
        // generate change event (disableFireEventValue=false)
        java.lang.reflect.Method m = oldValue.getClass().getDeclaredMethod(
          "_vmf_firePropertyChangeIfListenersArePresent",
          String.class, Object.class, Object.class);
        m.setAccessible(true);
        m.invoke(oldValue,
          "model", oldOpposite, null);
      } catch (Exception ex) {
        java.util.logging.Logger.getLogger(
           GrammarModelImpl.class.getName()).
           log(java.util.logging.Level.SEVERE, null, ex);
      }


    }

    // if new container is present then update containment relation
    if(typeMappings!=null) {
      //((eu.mihosoft.vmf.vmftext.grammar.TypeMappingsImpl)typeMappings)._vmf_setModelNoContainment(this);

      // remove 'typeMappings' object that shall be set from its previous parent
      // if it has one. for collections we perform this operation in the getter
      // method which registers a change listener that does all the work.
      if(typeMappings.getModel()!=null) {
        typeMappings.getModel().setTypeMappings(null);
      }


      try {
        java.lang.reflect.Field field =
          this.typeMappings.getClass().getDeclaredField("model");
        field.setAccessible(true);
        Object oldOpposite = field.get(this.typeMappings);
        field.set(this.typeMappings, this);
        // generate change event (disableFireEventValue=false)
        java.lang.reflect.Method m = this.typeMappings.getClass().getDeclaredMethod(
          "_vmf_firePropertyChangeIfListenersArePresent",
          String.class, Object.class, Object.class);
        m.setAccessible(true);
        m.invoke(this.typeMappings,
          "model", oldOpposite, this);
      } catch (Exception ex) {
        java.util.logging.Logger.getLogger(
           GrammarModelImpl.class.getName()).
           log(java.util.logging.Level.SEVERE, null, ex);
      }

    }
   

      if(this.typeMappings!=null && this!=null) {
        ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this)._vmf_references().add(this.typeMappings);
        ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this.typeMappings)._vmf_referencedBy().add(this);
      }

      if(oldValue!=null && this!=null) {
        ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)this)._vmf_references().add(oldValue);
        ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)oldValue)._vmf_referencedBy().add(this);
      }
  } // setterDeclaration (setter method)
  // internal API
  void _vmf_setTypeMappingsNoContainment(eu.mihosoft.vmf.vmftext.grammar.TypeMappings typeMappings) {
    // set the new value
    eu.mihosoft.vmf.vmftext.grammar.TypeMappings oldValue = this.typeMappings;
    this.typeMappings = typeMappings;

    // fire property change event
    _vmf_firePropertyChangeIfListenersArePresent("typeMappings", oldValue, this.typeMappings);
  }
   
  // --------------------------------------------------------------------
  // --- 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\":\"GrammarModel\"" +
        ", " + (this.customRules==null?"[]":this.customRules) +
          ", \"grammarName\": \"" + this.grammarName + "\"" +
          ", \"packageName\": \"" + this.packageName + "\"" +
          ", " + (this.ruleClasses==null?"[]":this.ruleClasses) +
          ", \"typeMappings\": \"" + this.typeMappings + "\"" +
           "}";
    } 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;

      // if object is read-only wrapper then unwrap the actual object
      if(o instanceof ReadOnlyGrammarModelImpl) {
        o = ((ReadOnlyGrammarModelImpl)o)._vmf_getMutableObject();
      }

      // -- try our interface/implementation --

      // perform the actual comparison for each property
      if (o instanceof GrammarModelImpl) {
        GrammarModelImpl other = (GrammarModelImpl) o;
        return           _vmf_equals(this.customRules, other.customRules) &&
          _vmf_equals(this.grammarName, other.grammarName) &&
          _vmf_equals(this.packageName, other.packageName) &&
          _vmf_equals(this.ruleClasses, other.ruleClasses) &&
          _vmf_equals(this.typeMappings, other.typeMappings);
      }

      // -- 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.customRules,            this.grammarName,            this.packageName,            this.ruleClasses,            this.typeMappings        );
            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 ------------------------------


  // --------------------------- BEGIN CLONING -----------------------------
  /**
   * Package private copy constructor.
   * It creates a deep or shallow copy of the specified other object.
   * @param other other object
   * @param deepCopy defines whether to perform a deep copy
   */
  GrammarModelImpl (
    GrammarModelImpl other,
    boolean deepCopy, java.util.IdentityHashMap identityMap
  ) {
    identityMap.put(other,this);

    if(deepCopy) {
      if(other.customRules!=null) {
        // element type is a model type
        for(CustomRule e : other.customRules) {
          // TODO do a bulk operation instead
          eu.mihosoft.vmf.runtime.core.internal.VObjectInternal eClone = (eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)(CustomRule)((VCloneableInternal)e)._vmf_deepCopy(identityMap);
          this.getCustomRules().add((CustomRule)eClone);
        }
       } else {
        // nothing to copy
      }
    } else {
      this.customRules = other.customRules;
    }
    if(this.customRules!=null) {
      this.customRules.forEach((e) -> {
          
        try {
          java.lang.reflect.Field field =
            e.getClass().getDeclaredField("model");
          field.setAccessible(true);
          Object oldOpposite = field.get(e);
          field.set(e, this);
          // generate change event (disableFireEventValue=false)
          java.lang.reflect.Method m = e.getClass().getDeclaredMethod(
            "_vmf_firePropertyChangeIfListenersArePresent",
            String.class, Object.class, Object.class);
          m.setAccessible(true);
          m.invoke(e,
            "model", oldOpposite, this);
        } catch (Exception ex) {
          java.util.logging.Logger.getLogger(
             GrammarModelImpl.class.getName()).
             log(java.util.logging.Level.SEVERE, null, ex);
        }

      });
    }
           // property type is an external type (TODO implement cloning strategy)
      this.setGrammarName(other.grammarName);
           // property type is an external type (TODO implement cloning strategy)
      this.setPackageName(other.packageName);
       if(deepCopy) {
      if(other.ruleClasses!=null) {
        // element type is a model type
        for(RuleClass e : other.ruleClasses) {
          // TODO do a bulk operation instead
          eu.mihosoft.vmf.runtime.core.internal.VObjectInternal eClone = (eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)(RuleClass)((VCloneableInternal)e)._vmf_deepCopy(identityMap);
          this.getRuleClasses().add((RuleClass)eClone);
        }
       } else {
        // nothing to copy
      }
    } else {
      this.ruleClasses = other.ruleClasses;
    }
    if(this.ruleClasses!=null) {
      this.ruleClasses.forEach((e) -> {
          
        try {
          java.lang.reflect.Field field =
            e.getClass().getDeclaredField("model");
          field.setAccessible(true);
          Object oldOpposite = field.get(e);
          field.set(e, this);
          // generate change event (disableFireEventValue=false)
          java.lang.reflect.Method m = e.getClass().getDeclaredMethod(
            "_vmf_firePropertyChangeIfListenersArePresent",
            String.class, Object.class, Object.class);
          m.setAccessible(true);
          m.invoke(e,
            "model", oldOpposite, this);
        } catch (Exception ex) {
          java.util.logging.Logger.getLogger(
             GrammarModelImpl.class.getName()).
             log(java.util.logging.Level.SEVERE, null, ex);
        }

      });
    }
          // property type is a model type
      if(deepCopy) {
        if(other.typeMappings!=null) {
          this.setTypeMappings((eu.mihosoft.vmf.vmftext.grammar.TypeMappings)((VCloneableInternal)other.typeMappings)._vmf_deepCopy(identityMap));
        }
      } else {
        this.typeMappings = other.typeMappings;
      }
    
   } // end copy constructor

   @Override
   public GrammarModelImpl _vmf_deepCopy(java.util.IdentityHashMap identityMap) {
      if(identityMap.containsKey(this)) {
        return (GrammarModelImpl)identityMap.get(this);
      } else {
        GrammarModelImpl clonedVal = new GrammarModelImpl(this, true, identityMap);
        return clonedVal;
      }
   }

   @Override
   public GrammarModelImpl _vmf_shallowCopy(java.util.IdentityHashMap identityMap) {
      if(identityMap.containsKey(this)) {
        return (GrammarModelImpl)identityMap.get(this);
      } else {
        GrammarModelImpl clonedVal = new GrammarModelImpl(this, false, identityMap);
        return clonedVal;
      }
   }
  @Override
  public GrammarModelImpl clone() /*throws CloneNotSupportedException*/ {
    // http://stackoverflow.com/questions/12886036/deep-copying-a-graph-structure
    // http://softwareengineering.stackexchange.com/questions/228848/how-does-java-handle-cyclic-data-references-when-serializing-an-object
    // https://gist.github.com/kanrourou/47223bdaf481505d4c7e
    // http://www.programcreek.com/2012/12/leetcode-clone-graph-java/
    java.util.IdentityHashMap identityMap =
      new java.util.IdentityHashMap<>();
    return _vmf_deepCopy(identityMap);
  }
  // ---------------------------- END CLONING ------------------------------


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

public static class BuilderImpl implements GrammarModel.Builder {

  private eu.mihosoft.vcollections.VList customRules;
  private java.lang.String grammarName;
  private java.lang.String packageName;
  private eu.mihosoft.vcollections.VList ruleClasses;
  private eu.mihosoft.vmf.vmftext.grammar.TypeMappings typeMappings;

  private boolean appendCollections = true;

  public BuilderImpl() {}

    public GrammarModel.Builder withCustomRules(eu.mihosoft.vcollections.VList customRules) {
      // ensure that this collection property is really immutable
      this.customRules = VList.newInstance(
        java.util.Collections.
        unmodifiableList(
          new java.util.ArrayList(customRules)
        )
      );
      return this;
    }
    public GrammarModel.Builder withGrammarName(java.lang.String grammarName) {
      this.grammarName = grammarName;
      return this;
    }
    public GrammarModel.Builder withPackageName(java.lang.String packageName) {
      this.packageName = packageName;
      return this;
    }
    public GrammarModel.Builder withRuleClasses(eu.mihosoft.vcollections.VList ruleClasses) {
      // ensure that this collection property is really immutable
      this.ruleClasses = VList.newInstance(
        java.util.Collections.
        unmodifiableList(
          new java.util.ArrayList(ruleClasses)
        )
      );
      return this;
    }
    public GrammarModel.Builder withTypeMappings(eu.mihosoft.vmf.vmftext.grammar.TypeMappings typeMappings) {
      this.typeMappings = typeMappings;
      return this;
    }

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

  public GrammarModel build() {
    GrammarModelImpl result = new GrammarModelImpl();
    if(this.customRules !=null) {
      result.getCustomRules().addAll(this.customRules);
    }
    result.grammarName = this.grammarName;
    result.packageName = this.packageName;
    if(this.ruleClasses !=null) {
      result.getRuleClasses().addAll(this.ruleClasses);
    }
    result.typeMappings = this.typeMappings;
    // PROP: typeMappings
        
      if(result.typeMappings!=null && result!=null) {
        ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)result)._vmf_references().add(result.typeMappings);
        ((eu.mihosoft.vmf.runtime.core.internal.VObjectInternal)result.typeMappings)._vmf_referencedBy().add(result);
      }

    return result;
  }

  public Builder applyFrom(GrammarModel o) {
      if(!this.appendCollections||this.customRules==null) {
        // ensure that this collection property is really immutable
        this.customRules = VList.newInstance(
          java.util.Collections.
          unmodifiableList(
              new java.util.ArrayList(o.getCustomRules())
          )
        );
      } else {
        this.customRules.addAll(o.getCustomRules());
      }
      this.grammarName = o.getGrammarName();
      this.packageName = o.getPackageName();
      if(!this.appendCollections||this.ruleClasses==null) {
        // ensure that this collection property is really immutable
        this.ruleClasses = VList.newInstance(
          java.util.Collections.
          unmodifiableList(
              new java.util.ArrayList(o.getRuleClasses())
          )
        );
      } else {
        this.ruleClasses.addAll(o.getRuleClasses());
      }
      this.typeMappings = o.getTypeMappings();

    return this;
  }
  public Builder applyTo(GrammarModel o) {

      if(!this.appendCollections) {
        o.getCustomRules().clear();
      }
      o.getCustomRules().addAll(customRules);
      o.setGrammarName(grammarName);
      o.setPackageName(packageName);
      if(!this.appendCollections) {
        o.getRuleClasses().clear();
      }
      o.getRuleClasses().addAll(ruleClasses);

    return this;
  }
} // end class BuilderImpl


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

  public boolean hasRootClass() {

    if(_vmf_delegate1==null) {
      _vmf_delegate1 = new eu.mihosoft.vmf.vmftext.grammar.GetRootClassDelegate();
      _vmf_delegate1.setCaller(this);
    }

    return _vmf_delegate1.hasRootClass();
  }

  public java.util.Optional propertyByName(java.lang.String arg0, java.lang.String arg1) {

    if(_vmf_delegate2==null) {
      _vmf_delegate2 = new eu.mihosoft.vmf.vmftext.grammar.RuleClassLookup();
      _vmf_delegate2.setCaller(this);
    }

    return _vmf_delegate2.propertyByName(arg0, arg1);
  }

  public eu.mihosoft.vmf.vmftext.grammar.RuleClass rootClass() {

    if(_vmf_delegate1==null) {
      _vmf_delegate1 = new eu.mihosoft.vmf.vmftext.grammar.GetRootClassDelegate();
      _vmf_delegate1.setCaller(this);
    }

    return _vmf_delegate1.rootClass();
  }

  public java.util.Optional ruleClassByName(java.lang.String arg0) {

    if(_vmf_delegate2==null) {
      _vmf_delegate2 = new eu.mihosoft.vmf.vmftext.grammar.RuleClassLookup();
      _vmf_delegate2.setCaller(this);
    }

    return _vmf_delegate2.ruleClassByName(arg0);
  }


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

  @Override
  public void addPropertyChangeListener(PropertyChangeListener l) {
      _vmf_getPropertyChanges().addPropertyChangeListener(l);
  }
  @Override
  public void removePropertyChangeListener(PropertyChangeListener l) {
      _vmf_getPropertyChanges().removePropertyChangeListener(l);

      if(_vmf_getPropertyChanges().getPropertyChangeListeners().length==0) {
          propertyChanges = null;
      }
  }

  private PropertyChangeSupport _vmf_getPropertyChanges() {

      if(propertyChanges==null) {
          propertyChanges = new PropertyChangeSupport(this);
      }

      return propertyChanges;
  }

  private boolean _vmf_hasListeners() {
      return propertyChanges!=null;
  }

  private void _vmf_firePropertyChangeIfListenersArePresent(
    String propertyName, Object oldValue, Object newValue) {
      if(_vmf_hasListeners()) {
          _vmf_getPropertyChanges().
                  firePropertyChange(propertyName, oldValue, newValue);
      }
  }

  // --------------------------------------------------------------------
  // --- 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(GrammarModelImpl.this);
            }
            public java.util.stream.Stream stream() {
              return eu.mihosoft.vmf.runtime.core.VIterator.of(GrammarModelImpl.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(GrammarModelImpl.this, strategy);
            }
            public java.util.stream.Stream stream(eu.mihosoft.vmf.runtime.core.VIterator.IterationStrategy strategy) {
              return eu.mihosoft.vmf.runtime.core.VIterator.of(GrammarModelImpl.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 GrammarModel deepCopy() {
               java.util.IdentityHashMap identityMap =
               new java.util.IdentityHashMap<>();
               return _vmf_deepCopy(identityMap);
            }

            @Override
            public GrammarModel shallowCopy() {
              return GrammarModelImpl.
                this._vmf_shallowCopy(new java.util.IdentityHashMap<>());
              }
            };
          }

          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(GrammarModelImpl.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(GrammarModelImpl.this);
            }

            return reflect;
          }


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

      return vmf;
  }

  private ReadOnlyGrammarModel readOnlyInstance;

  @Override
  public ReadOnlyGrammarModel asReadOnly() {

    if(readOnlyInstance==null) {
      readOnlyInstance = new eu.mihosoft.vmf.vmftext.grammar.impl.
        ReadOnlyGrammarModelImpl(this);
    }

    return readOnlyInstance;
  }

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

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

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


  static final String[] _VMF_PROPERTY_NAMES = {
    "customRules",
    "grammarName",
    "packageName",
    "ruleClasses",
    "typeMappings"
  };

  static final String[] _VMF_PROPERTY_TYPE_NAMES = {
    "eu.mihosoft.vcollections.VList", // type id -2
    "java.lang.String", // type id -1
    "java.lang.String", // type id -1
    "eu.mihosoft.vcollections.VList", // type id -2
    "eu.mihosoft.vmf.vmftext.grammar.TypeMappings"  // type id 36
  };

  static final int[] _VMF_PROPERTY_TYPES = {
       -2, // type eu.mihosoft.vcollections.VList
       -1, // type java.lang.String
       -1, // type java.lang.String
       -2, // type eu.mihosoft.vcollections.VList
       36  // type eu.mihosoft.vmf.vmftext.grammar.TypeMappings
  };


  /**
   * - 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 = {
        4  // type eu.mihosoft.vmf.vmftext.grammar.TypeMappings
  };

  /**
   * - indices of lists that contain model objects as elements
   */
  static final int[] _VMF_PROPERTIES_WITH_MODEL_ELEMENT_TYPES_INDICES = {
        0, // type eu.mihosoft.vcollections.VList
        3, // type eu.mihosoft.vcollections.VList
  };

  /**
   * - 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 = {
        0, // type eu.mihosoft.vcollections.VList
        3, // type eu.mihosoft.vcollections.VList
        4  // type eu.mihosoft.vmf.vmftext.grammar.TypeMappings
  };

  /**
   * - 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 = {
        0, // type eu.mihosoft.vcollections.VList
        3, // type eu.mihosoft.vcollections.VList
        4  // type eu.mihosoft.vmf.vmftext.grammar.TypeMappings
  };

  @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 getCustomRules();
      case 1:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getGrammarName();
      case 2:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getPackageName();
      case 3:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getRuleClasses();
      case 4:
        // TODO check whether we can prevent lazy initialized properties from
        //      being initialized just for iterating the object graph
        return getTypeMappings();
    }

    return null;
  }

  @Override
  public int _vmf_getPropertyIdByName(String propertyName) {
    switch(propertyName) {
      case "customRules":
        return 0;
      case "grammarName":
        return 1;
      case "packageName":
        return 2;
      case "ruleClasses":
        return 3;
      case "typeMappings":
        return 4;
      default:
        return -1;
    } // end switch
  }

  @Override
  public void _vmf_setPropertyValueById(int propertyId, Object value) {
    switch(propertyId) {
      case 1: // normal property (no collection and no containment)
        setGrammarName((java.lang.String)value);
        break;
      case 2: // normal property (no collection and no containment)
        setPackageName((java.lang.String)value);
        break;
      case 4: // normal property (no collection and no containment)
        setTypeMappings((eu.mihosoft.vmf.vmftext.grammar.TypeMappings)value);
        break;
      default:
            throw new RuntimeException("Cannot set property with id="+propertyId +": property is not writable.");
    } // end switch
  }

  @Override
  public Object _vmf_getDefaultValueById(int propertyId) {

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

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

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

      case 3:
        Object __vmf_default_value_tmpRuleClasses = _VMF_DEFAULT_VALUES[3];
        if(__vmf_default_value_tmpRuleClasses==null) {
            return null;
        } else {
            return __vmf_default_value_tmpRuleClasses;
        }

      case 4:
        Object __vmf_default_value_tmpTypeMappings = _VMF_DEFAULT_VALUES[4];
        if(__vmf_default_value_tmpTypeMappings==null) {
            return null;
        } else {
            return __vmf_default_value_tmpTypeMappings;
        }

    } // end switch

    return null;
  }

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

    // property customRules
    if(propertyId == 0) { 
      throw new RuntimeException("Cannot set default value for property 'customRules' with id="+propertyId +": property is a containment property and not writable.");
    }
    // property ruleClasses
    if(propertyId == 3) { 
      throw new RuntimeException("Cannot set default value for property 'ruleClasses' with id="+propertyId +": property is a containment property and not writable.");
    }
    // property typeMappings
    if(propertyId == 4) { 
      throw new RuntimeException("Cannot set default value for property 'typeMappings' with id="+propertyId +": property is a containment property and not writable.");
    }

    // if the value was previously unset then we need to update
    // the value to the new default value
    boolean isSetBeforeDefaultUpdate = _vmf_isSetById(propertyId);
    _VMF_DEFAULT_VALUES[propertyId] = defaultValue;
    if(!isSetBeforeDefaultUpdate) {
      _vmf_unsetById(propertyId);
    }
  }

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

  @Override
  public void _vmf_unsetById(int propertyId) {
    _vmf_setPropertyValueById(propertyId, _vmf_getDefaultValueById(propertyId));
  }

  final Object[] _VMF_DEFAULT_VALUES = {
    null, // type customRules (containment type, no defaut value possible)  
    null, // type grammarName   
    null, // type packageName   
    null, // type ruleClasses (containment type, no defaut value possible)  
    null  // type typeMappings (containment type, no defaut value possible)  
  };

  // --------------------------------------------------------------------
  // --- 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 - 2024 Weber Informatics LLC | Privacy Policy