content: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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
   * <p>
   * http://www.apache.org/licenses/LICENSE-2.0
   * <p>
   * 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 org.apache.atlas.model.discovery;
  
  import com.fasterxml.jackson.annotation.JsonAutoDetect;
  import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  import com.fasterxml.jackson.annotation.JsonInclude;
  import org.apache.atlas.model.instance.AtlasEntityHeader;
  import org.apache.atlas.model.instance.AtlasRelationshipHeader;
  import org.apache.commons.collections.CollectionUtils;
  import org.apache.commons.lang.StringUtils;
  
  import javax.xml.bind.annotation.XmlAccessType;
  import javax.xml.bind.annotation.XmlAccessorType;
  import javax.xml.bind.annotation.XmlRootElement;
  
  import java.io.Serializable;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Map;
  import java.util.Objects;
  
  import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
  import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
  
  @JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE)
  @JsonInclude(JsonInclude.Include.NON_NULL)
  @JsonIgnoreProperties(ignoreUnknown = true)
  public class AtlasSearchResult implements Serializable {
      private AtlasQueryType                 queryType;
      private SearchParameters               searchParameters;
      private String                         queryText;
      private String                         type;
      private String                         classification;
      private List<AtlasEntityHeader>        entities;
      private List<AtlasRelationshipHeader>  relations;
      private AttributeSearchResult          attributes;
      private List<AtlasFullTextResult>      fullTextResult;
      private Map<String, AtlasEntityHeader> referredEntities;
      private long                           approximateCount = -1;
      private String                         nextMarker;
  
      public AtlasSearchResult() {
      }
  
      public AtlasSearchResult(AtlasQueryType queryType) {
          this(null, queryType);
      }
  
      public AtlasSearchResult(String queryText, AtlasQueryType queryType) {
          setQueryText(queryText);
          setQueryType(queryType);
          setSearchParameters(null);
          setEntities(null);
          setRelations(null);
          setAttributes(null);
          setFullTextResult(null);
          setReferredEntities(null);
      }
  
      public AtlasSearchResult(SearchParameters searchParameters) {
          setQueryType(AtlasQueryType.BASIC);
  
          if (searchParameters != null) {
              setQueryText(searchParameters.getQuery());
              setSearchParameters(searchParameters);
              setEntities(null);
              setRelations(null);
              setAttributes(null);
              setFullTextResult(null);
              setReferredEntities(null);
          }
      }
  
      public AtlasQueryType getQueryType() {
          return queryType;
      }
  
      public void setQueryType(AtlasQueryType queryType) {
          this.queryType = queryType;
      }
  
      public SearchParameters getSearchParameters() {
          return searchParameters;
      }
  
      public void setSearchParameters(SearchParameters searchParameters) {
          this.searchParameters = searchParameters;
      }
  
      public String getQueryText() {
          return queryText;
      }
  
      public void setQueryText(String queryText) {
          this.queryText = queryText;
      }
  
      public String getType() {
          return type;
      }
  
      public void setType(String type) {
          this.type = type;
      }
  
      public String getClassification() {
          return classification;
      }
  
      public void setClassification(String classification) {
          this.classification = classification;
      }
  
      public List<AtlasEntityHeader> getEntities() {
          return entities;
      }
  
      public void setEntities(List<AtlasEntityHeader> entities) {
          this.entities = entities;
      }
  
      public List<AtlasRelationshipHeader> getRelations() {
          return relations;
      }
  
      public void setRelations(List<AtlasRelationshipHeader> relations) {
          this.relations = relations;
      }
  
      public AttributeSearchResult getAttributes() {
          return attributes;
      }
  
      public void setAttributes(AttributeSearchResult attributes) {
          this.attributes = attributes;
      }
  
      public List<AtlasFullTextResult> getFullTextResult() {
          return fullTextResult;
      }
  
      public void setFullTextResult(List<AtlasFullTextResult> fullTextResult) {
          this.fullTextResult = fullTextResult;
      }
  
      public Map<String, AtlasEntityHeader> getReferredEntities() {
          return referredEntities;
      }
  
      public void setReferredEntities(Map<String, AtlasEntityHeader> referredEntities) {
          this.referredEntities = referredEntities;
      }
  
      public long getApproximateCount() {
          return approximateCount;
      }
  
      public void setApproximateCount(long approximateCount) {
          this.approximateCount = approximateCount;
      }
  
      public String getNextMarker() {
          return nextMarker;
      }
  
      public void setNextMarker(String nextMarker) {
          this.nextMarker = nextMarker;
      }
  
      @Override
      public int hashCode() {
          return Objects.hash(queryType, searchParameters, queryText, type, classification, entities, relations, attributes, fullTextResult, referredEntities, nextMarker);
      }
  
      @Override
      public boolean equals(Object o) {
          if (this == o) {
              return true;
          } else if (o == null || getClass() != o.getClass()) {
              return false;
          }
  
          AtlasSearchResult that = (AtlasSearchResult) o;
  
          return Objects.equals(queryType, that.queryType) &&
                  Objects.equals(searchParameters, that.searchParameters) &&
                  Objects.equals(queryText, that.queryText) &&
                  Objects.equals(type, that.type) &&
                  Objects.equals(classification, that.classification) &&
                  Objects.equals(entities, that.entities) &&
                  Objects.equals(relations, that.relations) &&
                  Objects.equals(attributes, that.attributes) &&
                  Objects.equals(fullTextResult, that.fullTextResult) &&
                  Objects.equals(referredEntities, that.referredEntities) &&
                  Objects.equals(nextMarker, that.nextMarker);
      }
  
      @Override
      public String toString() {
          return "AtlasSearchResult{" +
                  "queryType=" + queryType +
                  ", searchParameters='" + searchParameters + '\'' +
                  ", queryText='" + queryText + '\'' +
                  ", type=" + type +
                  ", classification=" + classification +
                  ", entities=" + entities +
                  ", relations=" + relations +
                  ", attributes=" + attributes +
                  ", fullTextResult=" + fullTextResult +
                  ", referredEntities=" + referredEntities +
                  ", approximateCount=" + approximateCount +
                  ", nextMarker=" + nextMarker +
                  '}';
      }
  
      public void addEntity(AtlasEntityHeader newEntity) {
          if (entities == null) {
              entities = new ArrayList<>();
          }
  
          if (entities.isEmpty()) {
              entities.add(newEntity);
          } else {
              removeEntity(newEntity);
              entities.add(newEntity);
          }
      }
  
      public void removeEntity(AtlasEntityHeader entity) {
          List<AtlasEntityHeader> entities = this.entities;
  
          if (CollectionUtils.isNotEmpty(entities)) {
              entities.removeIf(currEntity -> StringUtils.equals(currEntity.getGuid(), entity.getGuid()));
          }
      }
  
      public void addRelation(AtlasRelationshipHeader relation) {
          if (relations == null) {
              relations = new ArrayList<>();
          }
  
          if (relations.isEmpty()) {
              relations.add(relation);
          } else {
              removeRelation(relation);
              relations.add(relation);
          }
      }
  
      public void removeRelation(AtlasRelationshipHeader relation) {
          List<AtlasRelationshipHeader> relations = this.relations;
  
          if (CollectionUtils.isNotEmpty(relations)) {
              relations.removeIf(currEntity -> StringUtils.equals(currEntity.getGuid(), relation.getGuid()));
          }
      }
  
      public enum AtlasQueryType { DSL, FULL_TEXT, GREMLIN, BASIC, ATTRIBUTE, RELATIONSHIP }
  
      @JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE)
      @JsonInclude(JsonInclude.Include.NON_NULL)
      @JsonIgnoreProperties(ignoreUnknown = true)
      @XmlRootElement
      @XmlAccessorType(XmlAccessType.PROPERTY)
      public static class AttributeSearchResult {
          private List<String>       name;
          private List<List<Object>> values;
  
          public AttributeSearchResult() {
          }
  
          public AttributeSearchResult(List<String> name, List<List<Object>> values) {
              this.name   = name;
              this.values = values;
          }
  
          public List<String> getName() {
              return name;
          }
  
          public void setName(List<String> name) {
              this.name = name;
          }
  
          public List<List<Object>> getValues() {
              return values;
          }
  
          public void setValues(List<List<Object>> values) {
              this.values = values;
          }
  
          @Override
          public int hashCode() {
              return Objects.hash(name, values);
          }
  
          @Override
          public boolean equals(Object o) {
              if (this == o) {
                  return true;
              } else if (o == null || getClass() != o.getClass()) {
                  return false;
              }
  
              AttributeSearchResult that = (AttributeSearchResult) o;
  
              return Objects.equals(name, that.name) &&
                      Objects.equals(values, that.values);
          }
  
          @Override
          public String toString() {
              return "AttributeSearchResult{" +
                      "name=" + name + ", " +
                      "values=" + values +
                      '}';
          }
      }
  
      @JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE)
      @JsonInclude(JsonInclude.Include.NON_NULL)
      @JsonIgnoreProperties(ignoreUnknown = true)
      @XmlRootElement
      @XmlAccessorType(XmlAccessType.PROPERTY)
      public static class AtlasFullTextResult {
          AtlasEntityHeader entity;
          Double            score;
  
          public AtlasFullTextResult() {
          }
  
          public AtlasFullTextResult(AtlasEntityHeader entity, Double score) {
              this.entity = entity;
              this.score  = score;
          }
  
          public AtlasEntityHeader getEntity() {
              return entity;
          }
  
          public void setEntity(AtlasEntityHeader entity) {
              this.entity = entity;
          }
  
          public Double getScore() {
              return score;
          }
  
          public void setScore(Double score) {
              this.score = score;
          }
  
          @Override
          public int hashCode() {
              return Objects.hash(entity, score);
          }
  
          @Override
          public boolean equals(Object o) {
              if (this == o) {
                  return true;
              } else if (o == null || getClass() != o.getClass()) {
                  return false;
              }
  
              AtlasFullTextResult that = (AtlasFullTextResult) o;
  
              return Objects.equals(entity, that.entity) &&
                      Objects.equals(score, that.score);
          }
  
          @Override
          public String toString() {
              return "AtlasFullTextResult{" +
                      "entity=" + entity +
                      ", score=" + score +
                      '}';
          }
      }
  }
  