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

com.orientechnologies.orient.core.sql.parser.OCreateLinkStatement Maven / Gradle / Ivy

There is a newer version: 3.2.32
Show newest version
/* Generated By:JJTree: Do not edit this line. OCreateLinkStatement.java Version 4.3 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=O,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.orientechnologies.orient.core.sql.parser;

import com.orientechnologies.common.exception.OException;
import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.db.record.ORecordLazyList;
import com.orientechnologies.orient.core.db.record.ORecordLazySet;
import com.orientechnologies.orient.core.exception.OCommandExecutionException;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.record.impl.ODocumentHelper;
import com.orientechnologies.orient.core.sql.OCommandSQLParsingException;
import com.orientechnologies.orient.core.sql.executor.OInternalResultSet;
import com.orientechnologies.orient.core.sql.executor.OResultInternal;
import com.orientechnologies.orient.core.sql.executor.OResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class OCreateLinkStatement extends OSimpleExecStatement {

  protected OIdentifier name;
  protected OIdentifier type;
  protected OIdentifier sourceClass;
  protected OIdentifier sourceField;
  protected ORecordAttribute sourceRecordAttr;
  protected OIdentifier destClass;
  protected OIdentifier destField;
  protected ORecordAttribute destRecordAttr;
  protected boolean inverse = false;

  boolean breakExec = false; // for timeout

  public OCreateLinkStatement(int id) {
    super(id);
  }

  public OCreateLinkStatement(OrientSql p, int id) {
    super(p, id);
  }

  @Override
  public OResultSet executeSimple(OCommandContext ctx) {
    execute(ctx);
    OInternalResultSet rs = new OInternalResultSet();
    OResultInternal result = new OResultInternal();
    result.setProperty("operation", "create link");
    result.setProperty("name", name.getValue());
    result.setProperty("fromClass", sourceClass.getStringValue());
    result.setProperty("toClass", destClass.getStringValue());
    rs.add(result);
    return rs;
  }

  /** Execute the CREATE LINK. */
  private Object execute(OCommandContext ctx) {
    if (destField == null)
      throw new OCommandExecutionException(
          "Cannot execute the command because it has not been parsed yet");

    final ODatabaseDocumentInternal database = getDatabase();
    if (!(database.getDatabaseOwner() instanceof ODatabaseDocument))
      throw new OCommandSQLParsingException(
          "This command supports only the database type ODatabaseDocumentTx and type '"
              + database.getClass()
              + "' was found");

    final ODatabaseDocument db = (ODatabaseDocument) database.getDatabaseOwner();

    OClass sourceClass =
        database
            .getMetadata()
            .getImmutableSchemaSnapshot()
            .getClass(getSourceClass().getStringValue());
    if (sourceClass == null)
      throw new OCommandExecutionException(
          "Source class '" + getSourceClass().getStringValue() + "' not found");

    OClass destClass =
        database
            .getMetadata()
            .getImmutableSchemaSnapshot()
            .getClass(getDestClass().getStringValue());
    if (destClass == null)
      throw new OCommandExecutionException(
          "Destination class '" + getDestClass().getStringValue() + "' not found");

    Object value;

    String cmd = "select from ";
    if (destField != null && !ODocumentHelper.ATTRIBUTE_RID.equals(destField.value)) {
      cmd = "select from " + getDestClass() + " where " + destField + " = ";
    }

    List result;
    ODocument target;
    Object oldValue;
    long total = 0;

    String linkName = name == null ? sourceField.getStringValue() : name.getStringValue();

    boolean multipleRelationship;
    OType linkType = OType.valueOf(type.getStringValue().toUpperCase(Locale.ENGLISH));
    if (linkType != null)
      // DETERMINE BASED ON FORCED TYPE
      multipleRelationship = linkType == OType.LINKSET || linkType == OType.LINKLIST;
    else multipleRelationship = false;

    try {
      // BROWSE ALL THE RECORDS OF THE SOURCE CLASS
      for (ODocument doc : db.browseClass(sourceClass.getName())) {
        if (breakExec) {
          break;
        }
        value = doc.getProperty(sourceField.getStringValue());

        if (value != null) {
          if (value instanceof ODocument || value instanceof ORID) {
            // ALREADY CONVERTED
          } else if (value instanceof Collection) {
            // TODO
          } else {
            // SEARCH THE DESTINATION RECORD
            target = null;

            if (destField != null
                && !ODocumentHelper.ATTRIBUTE_RID.equals(destField.value)
                && value instanceof String)
              if (((String) value).length() == 0) value = null;
              else value = "'" + value + "'";

            try (OResultSet rs = database.query(cmd + value)) {
              result = toList(rs);
            }

            if (result == null || result.size() == 0) value = null;
            else if (result.size() > 1)
              throw new OCommandExecutionException(
                  "Cannot create link because multiple records was found in class '"
                      + destClass.getName()
                      + "' with value "
                      + value
                      + " in field '"
                      + destField
                      + "'");
            else {
              target = result.get(0);
              value = target;
            }

            if (target != null && inverse) {
              // INVERSE RELATIONSHIP
              oldValue = target.getProperty(linkName);

              if (oldValue != null) {
                if (!multipleRelationship) multipleRelationship = true;

                Collection coll;
                if (oldValue instanceof Collection) {
                  // ADD IT IN THE EXISTENT COLLECTION
                  coll = (Collection) oldValue;
                  target.setDirty();
                } else {
                  // CREATE A NEW COLLECTION FOR BOTH
                  coll = new ArrayList(2);
                  target.setProperty(linkName, coll);
                  coll.add((ODocument) oldValue);
                }
                coll.add(doc);
              } else {
                if (linkType != null)
                  if (linkType == OType.LINKSET) {
                    value = new ORecordLazySet(target);
                    ((Set) value).add(doc);
                  } else if (linkType == OType.LINKLIST) {
                    value = new ORecordLazyList(target);
                    ((ORecordLazyList) value).add(doc);
                  } else
                    // IGNORE THE TYPE, SET IT AS LINK
                    value = doc;
                else value = doc;

                target.setProperty(linkName, value);
              }
              target.save();

            } else {
              // SET THE REFERENCE
              doc.setProperty(linkName, value);
              doc.save();
            }

            total++;
          }
        }
      }

      if (total > 0) {
        if (inverse) {
          // REMOVE THE OLD PROPERTY IF ANY
          OProperty prop = destClass.getProperty(linkName);
          destClass = db.getMetadata().getSchema().getClass(getDestClass().getStringValue());
          if (prop != null) destClass.dropProperty(linkName);

          if (linkType == null) linkType = multipleRelationship ? OType.LINKSET : OType.LINK;

          // CREATE THE PROPERTY
          destClass.createProperty(linkName, linkType, sourceClass);

        } else {

          // REMOVE THE OLD PROPERTY IF ANY
          OProperty prop = sourceClass.getProperty(linkName);
          sourceClass = db.getMetadata().getSchema().getClass(getDestClass().getStringValue());
          if (prop != null) sourceClass.dropProperty(linkName);

          // CREATE THE PROPERTY
          sourceClass.createProperty(linkName, OType.LINK, destClass);
        }
      }
    } catch (Exception e) {
      throw OException.wrapException(
          new OCommandExecutionException("Error on creation of links"), e);
    }
    return total;
  }

  private List toList(OResultSet rs) {
    if (!rs.hasNext()) {
      return null;
    }
    List result = new ArrayList<>();
    while (rs.hasNext()) {
      result.add((ODocument) rs.next().getElement().orElse(null));
    }
    return result;
  }

  @Override
  public void toString(Map params, StringBuilder builder) {
    builder.append("CREATE LINK ");
    name.toString(params, builder);
    builder.append(" TYPE ");
    type.toString(params, builder);
    builder.append(" FROM ");
    sourceClass.toString(params, builder);
    builder.append(".");
    if (sourceField != null) {
      sourceField.toString(params, builder);
    } else {
      sourceRecordAttr.toString(params, builder);
    }
    builder.append(" TO ");
    destClass.toString(params, builder);
    builder.append(".");
    if (destField != null) {
      destField.toString(params, builder);
    } else {
      destRecordAttr.toString(params, builder);
    }
    if (inverse) {
      builder.append(" INVERSE");
    }
  }

  @Override
  public void toGenericStatement(StringBuilder builder) {
    builder.append("CREATE LINK ");
    name.toGenericStatement(builder);
    builder.append(" TYPE ");
    type.toGenericStatement(builder);
    builder.append(" FROM ");
    sourceClass.toGenericStatement(builder);
    builder.append(".");
    if (sourceField != null) {
      sourceField.toGenericStatement(builder);
    } else {
      sourceRecordAttr.toGenericStatement(builder);
    }
    builder.append(" TO ");
    destClass.toGenericStatement(builder);
    builder.append(".");
    if (destField != null) {
      destField.toGenericStatement(builder);
    } else {
      destRecordAttr.toGenericStatement(builder);
    }
    if (inverse) {
      builder.append(" INVERSE");
    }
  }

  @Override
  public OCreateLinkStatement copy() {
    OCreateLinkStatement result = new OCreateLinkStatement(-1);
    result.name = name == null ? null : name.copy();
    result.type = type == null ? null : type.copy();
    result.sourceClass = sourceClass == null ? null : sourceClass.copy();
    result.sourceField = sourceField == null ? null : sourceField.copy();
    result.sourceRecordAttr = sourceRecordAttr == null ? null : sourceRecordAttr.copy();
    result.destClass = destClass == null ? null : destClass.copy();
    result.destField = destField == null ? null : destField.copy();
    result.destRecordAttr = destRecordAttr == null ? null : destRecordAttr.copy();
    result.inverse = inverse;
    return result;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    OCreateLinkStatement that = (OCreateLinkStatement) o;

    if (inverse != that.inverse) return false;
    if (name != null ? !name.equals(that.name) : that.name != null) return false;
    if (type != null ? !type.equals(that.type) : that.type != null) return false;
    if (sourceClass != null ? !sourceClass.equals(that.sourceClass) : that.sourceClass != null)
      return false;
    if (sourceField != null ? !sourceField.equals(that.sourceField) : that.sourceField != null)
      return false;
    if (sourceRecordAttr != null
        ? !sourceRecordAttr.equals(that.sourceRecordAttr)
        : that.sourceRecordAttr != null) return false;
    if (destClass != null ? !destClass.equals(that.destClass) : that.destClass != null)
      return false;
    if (destField != null ? !destField.equals(that.destField) : that.destField != null)
      return false;
    if (destRecordAttr != null
        ? !destRecordAttr.equals(that.destRecordAttr)
        : that.destRecordAttr != null) return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + (type != null ? type.hashCode() : 0);
    result = 31 * result + (sourceClass != null ? sourceClass.hashCode() : 0);
    result = 31 * result + (sourceField != null ? sourceField.hashCode() : 0);
    result = 31 * result + (sourceRecordAttr != null ? sourceRecordAttr.hashCode() : 0);
    result = 31 * result + (destClass != null ? destClass.hashCode() : 0);
    result = 31 * result + (destField != null ? destField.hashCode() : 0);
    result = 31 * result + (destRecordAttr != null ? destRecordAttr.hashCode() : 0);
    result = 31 * result + (inverse ? 1 : 0);
    return result;
  }

  public OIdentifier getName() {
    return name;
  }

  public OIdentifier getType() {
    return type;
  }

  public OIdentifier getSourceClass() {
    return sourceClass;
  }

  public OIdentifier getSourceField() {
    return sourceField;
  }

  public ORecordAttribute getSourceRecordAttr() {
    return sourceRecordAttr;
  }

  public OIdentifier getDestClass() {
    return destClass;
  }

  public OIdentifier getDestField() {
    return destField;
  }

  public ORecordAttribute getDestRecordAttr() {
    return destRecordAttr;
  }

  public boolean isInverse() {
    return inverse;
  }
}
/* JavaCC - OriginalChecksum=de46c9bdaf3b36691764a78cd89d1c2b (do not edit this line) */




© 2015 - 2024 Weber Informatics LLC | Privacy Policy