content: /*
   * Copyright 1999-2017 Alibaba Group Holding Ltd.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.alibaba.druid.sql.dialect.oracle.ast.clause;
  
  import com.alibaba.druid.sql.ast.*;
  import com.alibaba.druid.sql.ast.statement.SQLSelect;
  import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;
  import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr;
  import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
  import com.alibaba.druid.sql.visitor.SQLASTVisitor;
  
  import java.util.ArrayList;
  import java.util.List;
  
  public class ModelClause extends OracleSQLObjectImpl {
      private final List<CellReferenceOption> cellReferenceOptions = new ArrayList<CellReferenceOption>();
      private ReturnRowsClause returnRowsClause;
      private final List<ReferenceModelClause> referenceModelClauses = new ArrayList<ReferenceModelClause>();
      private MainModelClause mainModel;
  
      @Override
      public void accept0(OracleASTVisitor visitor) {
          if (visitor.visit(this)) {
              acceptChild(visitor, returnRowsClause);
              acceptChild(visitor, referenceModelClauses);
              acceptChild(visitor, mainModel);
          }
          visitor.endVisit(this);
      }
  
      public MainModelClause getMainModel() {
          return mainModel;
      }
  
      public void setMainModel(MainModelClause mainModel) {
          this.mainModel = mainModel;
      }
  
      public ReturnRowsClause getReturnRowsClause() {
          return returnRowsClause;
      }
  
      public void setReturnRowsClause(ReturnRowsClause returnRowsClause) {
          this.returnRowsClause = returnRowsClause;
      }
  
      public List<ReferenceModelClause> getReferenceModelClauses() {
          return referenceModelClauses;
      }
  
      public List<CellReferenceOption> getCellReferenceOptions() {
          return cellReferenceOptions;
      }
  
      public static enum CellReferenceOption {
          IgnoreNav("IGNORE NAV"), KeepNav("KEEP NAV"), UniqueDimension("UNIQUE DIMENSION"),
          UniqueSingleReference("UNIQUE SINGLE REFERENCE");
  
          public final String name;
  
          CellReferenceOption() {
              this(null);
          }
  
          CellReferenceOption(String name) {
              this.name = name;
          }
  
          public String toString() {
              return name;
          }
  
      }
  
      public static class ReturnRowsClause extends OracleSQLObjectImpl {
          private boolean all;
  
          public boolean isAll() {
              return all;
          }
  
          public void setAll(boolean all) {
              this.all = all;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              visitor.visit(this);
              visitor.endVisit(this);
          }
      }
  
      public static class ReferenceModelClause extends OracleSQLObjectImpl {
          private SQLExpr name;
          private SQLSelect subQuery;
          private final List<CellReferenceOption> cellReferenceOptions = new ArrayList<CellReferenceOption>();
  
          public List<CellReferenceOption> getCellReferenceOptions() {
              return cellReferenceOptions;
          }
  
          public SQLExpr getName() {
              return name;
          }
  
          public void setName(SQLExpr name) {
              this.name = name;
          }
  
          public SQLSelect getSubQuery() {
              return subQuery;
          }
  
          public void setSubQuery(SQLSelect subQuery) {
              this.subQuery = subQuery;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
          }
      }
  
      public static class ModelColumnClause extends OracleSQLObjectImpl {
          private QueryPartitionClause queryPartitionClause;
          private String alias;
          private final List<ModelColumn> dimensionByColumns = new ArrayList<ModelColumn>();
          private final List<ModelColumn> measuresColumns = new ArrayList<ModelColumn>();
  
          public List<ModelColumn> getDimensionByColumns() {
              return dimensionByColumns;
          }
  
          public List<ModelColumn> getMeasuresColumns() {
              return measuresColumns;
          }
  
          public QueryPartitionClause getQueryPartitionClause() {
              return queryPartitionClause;
          }
  
          public void setQueryPartitionClause(QueryPartitionClause queryPartitionClause) {
              this.queryPartitionClause = queryPartitionClause;
          }
  
          public String getAlias() {
              return alias;
          }
  
          public void setAlias(String alias) {
              this.alias = alias;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, queryPartitionClause);
                  acceptChild(visitor, dimensionByColumns);
                  acceptChild(visitor, measuresColumns);
              }
              visitor.endVisit(this);
          }
  
      }
  
      public static class ModelColumn extends OracleSQLObjectImpl {
          private SQLExpr expr;
          private String alias;
  
          public SQLExpr getExpr() {
              return expr;
          }
  
          public void setExpr(SQLExpr expr) {
              this.expr = expr;
          }
  
          public String getAlias() {
              return alias;
          }
  
          public void setAlias(String alias) {
              this.alias = alias;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, expr);
              }
              visitor.endVisit(this);
          }
  
      }
  
      public static class QueryPartitionClause extends OracleSQLObjectImpl {
          private List<SQLExpr> exprList = new ArrayList<SQLExpr>();
  
          public List<SQLExpr> getExprList() {
              return exprList;
          }
  
          public void setExprList(List<SQLExpr> exprList) {
              this.exprList = exprList;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, exprList);
              }
          }
  
      }
  
      public static class MainModelClause extends OracleSQLObjectImpl {
          private SQLExpr mainModelName;
          private ModelColumnClause modelColumnClause;
  
          private final List<CellReferenceOption> cellReferenceOptions = new ArrayList<CellReferenceOption>();
          private ModelRulesClause modelRulesClause;
  
          public ModelRulesClause getModelRulesClause() {
              return modelRulesClause;
          }
  
          public void setModelRulesClause(ModelRulesClause modelRulesClause) {
              this.modelRulesClause = modelRulesClause;
          }
  
          public List<CellReferenceOption> getCellReferenceOptions() {
              return cellReferenceOptions;
          }
  
          public ModelColumnClause getModelColumnClause() {
              return modelColumnClause;
          }
  
          public void setModelColumnClause(ModelColumnClause modelColumnClause) {
              this.modelColumnClause = modelColumnClause;
          }
  
          public SQLExpr getMainModelName() {
              return mainModelName;
          }
  
          public void setMainModelName(SQLExpr mainModelName) {
              this.mainModelName = mainModelName;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, mainModelName);
                  acceptChild(visitor, modelColumnClause);
                  acceptChild(visitor, modelRulesClause);
              }
              visitor.endVisit(this);
          }
  
      }
  
      public static class ModelRulesClause extends OracleSQLObjectImpl {
          private final List<ModelRuleOption> options = new ArrayList<ModelRuleOption>();
          private SQLExpr iterate;
          private SQLExpr until;
          private final List<CellAssignmentItem> cellAssignmentItems = new ArrayList<CellAssignmentItem>();
  
          public SQLExpr getUntil() {
              return until;
          }
  
          public void setUntil(SQLExpr until) {
              this.until = until;
          }
  
          public SQLExpr getIterate() {
              return iterate;
          }
  
          public void setIterate(SQLExpr iterate) {
              this.iterate = iterate;
          }
  
          public List<ModelRuleOption> getOptions() {
              return options;
          }
  
          public List<CellAssignmentItem> getCellAssignmentItems() {
              return cellAssignmentItems;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, iterate);
                  acceptChild(visitor, until);
                  acceptChild(visitor, cellAssignmentItems);
              }
              visitor.endVisit(this);
          }
  
      }
  
      public static enum ModelRuleOption {
          UPSERT("UPSERT"), UPDATE("UPDATE"), AUTOMATIC_ORDER("AUTOMATIC ORDER"), SEQUENTIAL_ORDER("SEQUENTIAL ORDER");
  
          public final String name;
  
          ModelRuleOption(String name) {
              this.name = name;
          }
  
          public String toString() {
              return name;
          }
      }
  
      public static class CellAssignmentItem extends OracleSQLObjectImpl {
          private ModelRuleOption option;
          private CellAssignment cellAssignment;
          private SQLOrderBy orderBy;
          private SQLExpr expr;
  
          public ModelRuleOption getOption() {
              return option;
          }
  
          public void setOption(ModelRuleOption option) {
              this.option = option;
          }
  
          public CellAssignment getCellAssignment() {
              return cellAssignment;
          }
  
          public void setCellAssignment(CellAssignment cellAssignment) {
              this.cellAssignment = cellAssignment;
          }
  
          public SQLOrderBy getOrderBy() {
              return orderBy;
          }
  
          public void setOrderBy(SQLOrderBy orderBy) {
              this.orderBy = orderBy;
          }
  
          public SQLExpr getExpr() {
              return expr;
          }
  
          public void setExpr(SQLExpr expr) {
              this.expr = expr;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, cellAssignment);
                  acceptChild(visitor, orderBy);
                  acceptChild(visitor, expr);
              }
              visitor.endVisit(this);
          }
  
      }
  
      public static class CellAssignment extends SQLExprImpl implements OracleExpr, SQLReplaceable {
          private SQLExpr measureColumn;
          private final List<SQLExpr> conditions = new ArrayList<SQLExpr>();
  
          public List<SQLExpr> getConditions() {
              return conditions;
          }
  
          public SQLExpr getMeasureColumn() {
              return measureColumn;
          }
  
          public void setMeasureColumn(SQLExpr e) {
              if (e != null) {
                  e.setParent(this);
              }
              this.measureColumn = e;
          }
  
          @Override
          public boolean replace(SQLExpr expr, SQLExpr target) {
              if (this.measureColumn == expr) {
                  setMeasureColumn(target);
                  return true;
              }
  
              for (int i = 0; i < conditions.size(); i++) {
                  if (conditions.get(i) == expr) {
                      target.setParent(this);
                      conditions.set(i, target);
                      return true;
                  }
              }
  
              return false;
          }
  
          @Override
          public void accept0(OracleASTVisitor visitor) {
              if (visitor.visit(this)) {
                  acceptChild(visitor, measureColumn);
                  acceptChild(visitor, conditions);
              }
              visitor.endVisit(this);
          }
  
          @Override
          public boolean equals(Object o) {
              if (this == o) {
                  return true;
              }
              if (o == null || getClass() != o.getClass()) {
                  return false;
              }
  
              CellAssignment that = (CellAssignment) o;
  
              if (measureColumn != null ? !measureColumn.equals(that.measureColumn) : that.measureColumn != null) {
                  return false;
              }
              return conditions.equals(that.conditions);
          }
  
          @Override
          public int hashCode() {
              int result = measureColumn != null ? measureColumn.hashCode() : 0;
              result = 31 * result + conditions.hashCode();
              return result;
          }
  
          @Override
          protected void accept0(SQLASTVisitor visitor) {
              accept0((OracleASTVisitor) visitor);
          }
  
          @Override
          public SQLExpr clone() {
              CellAssignment x = new CellAssignment();
              if (measureColumn != null) {
                  x.setMeasureColumn(measureColumn.clone());
              }
              return null;
          }
  
          @Override
          public List<SQLObject> getChildren() {
              List children = new ArrayList();
              children.add(measureColumn);
              children.addAll(conditions);
              return children;
          }
      }
  
      public ModelClause clone() {
          throw new UnsupportedOperationException();
      }
  }
  