/**
   * Convenience function. Return true if the manyToOne link is eventually pointing back to an
   * instance of the same class
   *
   * @param alsoCheckNullable
   * @param link
   * @return true if the manyToOne link is eventually pointing back to an instance of the same class
   */
  public final boolean isCyclicReference(boolean alsoCheckNullable, PropertyObj link) {
    boolean result = false;

    if (this.isManyToOne()) {
      // get cycle list for this table, if available
      LinkedList<String> cycleList =
          State.getInstance()
              .commitResult
              .getCycleList()
              .get(this.getClazz().getTableObj().getFullTableName());
      // get the table object of the target
      TableObj targetTable = link.getClazz().getTableObj();

      TableObj cycleTable = null;
      if (cycleList != null) {
        // we had an entry. Fetch the last table
        cycleTable = State.getInstance().tables.get(cycleList.getLast());
      }
      // we have a self-loop or an entry in the cycle list pertaining to this record
      result = this.getClazz().equals(link.getClazz()) || targetTable.equals(cycleTable);

      if (alsoCheckNullable && (!this.getFieldObj().isNullable())) {
        result = false;
      }
    }

    return result;
  }
  /**
   * Checks to see if this property has a match in the cascade list to return if enabled or
   * disabled.
   *
   * @param state
   * @param propertyObj
   * @return t/f
   */
  private boolean isXToXCascadeEnabledByConfig(
      TreeMap<String, CascadeState> state, PropertyObj target) {
    if (target == null) {
      return false;
    }
    String classPackage = this.getClazz().getClassPackage();
    String className = this.getClazz().getClassName();

    String targetClassPackage = target.getClazz().getClassPackage();
    String targetClassName = target.getClazz().getClassName();
    String targetPropertyName = target.getPropertyName();

    CascadeState match =
        matchCascade(
            state,
            "*.*.*",
            "*." + className + ".*",
            "*." + className + "." + propertyName,
            classPackage + ".*." + propertyName,
            classPackage + ".*.*",
            classPackage + "." + className + ".*",
            "*.*." + propertyName,
            classPackage + "." + className + "." + propertyName);

    if (match == null) {
      match =
          matchCascade(
              state,
              "to:*.*.*",
              "to:*." + targetClassName + ".*",
              "to:*." + targetClassName + "." + targetPropertyName,
              "to:" + targetClassPackage + ".*." + targetPropertyName,
              "to:" + targetClassPackage + ".*.*",
              "to:" + targetClassPackage + "." + targetClassName + ".*",
              "to:*.*." + targetPropertyName,
              "to:" + targetClassPackage + "." + targetClassName + "." + targetPropertyName);
    }
    // get the default
    boolean enableCascading = state.get("*").isCascadeEnabled();

    if (match != null) {
      // we're using: default... EXCEPT
      enableCascading = match.isCascadeEnabled();
    }

    return enableCascading;
  }
  /**
   * Checks to see if this property has a match in the cascade list to return if enabled or
   * disabled.
   *
   * @param state
   * @param propertyObj
   * @return t/f
   */
  private Set<String> getXToXCascadeType(TreeMap<String, CascadeState> state, PropertyObj target) {

    String classPackage = this.getClazz().getClassPackage();
    String className = this.getClazz().getClassName();

    String targetClassPackage = target.getClazz().getClassPackage();
    String targetClassName = target.getClazz().getClassName();
    String targetPropertyName = target.getPropertyName();

    CascadeState match =
        matchCascade(
            state,
            "*.*.*",
            "*." + className + ".*",
            "*." + className + "." + this.propertyName,
            classPackage + ".*." + this.propertyName,
            classPackage + ".*.*",
            classPackage + "." + className + ".*",
            "*.*." + this.propertyName,
            classPackage + "." + className + "." + this.propertyName);

    if (match == null) {
      match =
          matchCascade(
              state,
              "to:*.*.*",
              "to:*." + targetClassName + ".*",
              "to:*." + targetClassName + "." + targetPropertyName,
              "to:" + targetClassPackage + ".*." + targetPropertyName,
              "to:" + targetClassPackage + ".*.*",
              "to:" + targetClassPackage + "." + targetClassName + ".*",
              "to:*.*." + targetPropertyName,
              "to:" + targetClassPackage + "." + targetClassName + "." + targetPropertyName);
    }
    // get the default
    Set<String> cascadeType = state.get("*").getCascadeType();

    if (match != null) {
      // we're using: default... EXCEPT
      cascadeType = match.getCascadeType();
    }

    return cascadeType;
  }