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.typedef;
  
  import com.fasterxml.jackson.annotation.JsonAutoDetect;
  import com.fasterxml.jackson.annotation.JsonIgnore;
  import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  import com.fasterxml.jackson.annotation.JsonInclude;
  import org.apache.atlas.model.TypeCategory;
  import org.apache.commons.collections.CollectionUtils;
  import org.apache.commons.collections.MapUtils;
  
  import javax.xml.bind.annotation.XmlAccessType;
  import javax.xml.bind.annotation.XmlAccessorType;
  import javax.xml.bind.annotation.XmlRootElement;
  
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Objects;
  import java.util.TimeZone;
  
  import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
  import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
  
  /**
   * Base class that captures common-attributes for all Atlas types.
   */
  @JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE)
  @JsonInclude(JsonInclude.Include.NON_NULL)
  @JsonIgnoreProperties(ignoreUnknown = true)
  @XmlRootElement
  @XmlAccessorType(XmlAccessType.PROPERTY)
  public abstract class AtlasBaseTypeDef implements java.io.Serializable {
      private static final long serialVersionUID = 1L;
  
      public static final String ATLAS_TYPE_BOOLEAN         = "boolean";
      public static final String ATLAS_TYPE_BYTE            = "byte";
      public static final String ATLAS_TYPE_SHORT           = "short";
      public static final String ATLAS_TYPE_INT             = "int";
      public static final String ATLAS_TYPE_LONG            = "long";
      public static final String ATLAS_TYPE_FLOAT           = "float";
      public static final String ATLAS_TYPE_DOUBLE          = "double";
      public static final String ATLAS_TYPE_BIGINTEGER      = "biginteger";
      public static final String ATLAS_TYPE_BIGDECIMAL      = "bigdecimal";
      public static final String ATLAS_TYPE_STRING          = "string";
      public static final String ATLAS_TYPE_DATE            = "date";
      public static final String ATLAS_TYPE_OBJECT_ID       = "objectid";
      public static final String ATLAS_TYPE_ARRAY_PREFIX    = "array<";
      public static final String ATLAS_TYPE_ARRAY_SUFFIX    = ">";
      public static final String ATLAS_TYPE_MAP_PREFIX      = "map<";
      public static final String ATLAS_TYPE_MAP_KEY_VAL_SEP = ",";
      public static final String ATLAS_TYPE_MAP_SUFFIX      = ">";
      public static final String ATLAS_TYPE_PROCESS         = "Process";
      public static final String ATLAS_TYPE_DATASET         = "DataSet";
      public static final String ATLAS_TYPE_ASSET           = "Asset";
      public static final String SERVICE_TYPE_ATLAS_CORE    = "atlas_core";
      public static final String SERIALIZED_DATE_FORMAT_STR = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
      public static final String ATLAS_TYPE_INFRASTRUCTURE       = "Infrastructure";
      public static final String TYPEDEF_OPTION_SUPPORTS_SCHEMA  = "supportsSchema";
      public static final String TYPEDEF_OPTION_SUPPORTS_PROFILE = "supportsProfile";
  
      public static final String[] ATLAS_PRIMITIVE_TYPES = {
              ATLAS_TYPE_BOOLEAN,
              ATLAS_TYPE_BYTE,
              ATLAS_TYPE_SHORT,
              ATLAS_TYPE_INT,
              ATLAS_TYPE_LONG,
              ATLAS_TYPE_FLOAT,
              ATLAS_TYPE_DOUBLE,
              ATLAS_TYPE_BIGINTEGER,
              ATLAS_TYPE_BIGDECIMAL,
              ATLAS_TYPE_STRING,
      };
  
      /**
       * The list of types that are valid for relationships. These are the
       * primitive attributes and date.
       */
      public static final String[] ATLAS_RELATIONSHIP_ATTRIBUTE_TYPES = {
              ATLAS_TYPE_BOOLEAN,
              ATLAS_TYPE_BYTE,
              ATLAS_TYPE_SHORT,
              ATLAS_TYPE_INT,
              ATLAS_TYPE_LONG,
              ATLAS_TYPE_FLOAT,
              ATLAS_TYPE_DOUBLE,
              ATLAS_TYPE_BIGINTEGER,
              ATLAS_TYPE_BIGDECIMAL,
              ATLAS_TYPE_STRING,
              ATLAS_TYPE_DATE
      };
  
      public static final String[] ATLAS_BUILTIN_TYPES = {
              ATLAS_TYPE_BOOLEAN,
              ATLAS_TYPE_BYTE,
              ATLAS_TYPE_SHORT,
              ATLAS_TYPE_INT,
              ATLAS_TYPE_LONG,
              ATLAS_TYPE_FLOAT,
              ATLAS_TYPE_DOUBLE,
              ATLAS_TYPE_BIGINTEGER,
              ATLAS_TYPE_BIGDECIMAL,
              ATLAS_TYPE_STRING,
  
              ATLAS_TYPE_DATE,
              ATLAS_TYPE_OBJECT_ID,
      };
  
      @Deprecated
      public static final DateFormat DATE_FORMATTER = new SimpleDateFormat(SERIALIZED_DATE_FORMAT_STR);
  
      private static final ThreadLocal<DateFormat> THREAD_LOCAL_DATE_FORMAT = ThreadLocal.withInitial(() -> {
          DateFormat ret = new SimpleDateFormat(SERIALIZED_DATE_FORMAT_STR);
  
          ret.setTimeZone(TimeZone.getTimeZone("UTC"));
  
          return ret;
      });
  
      private final TypeCategory        category;
      private       String              guid;
      private       String              createdBy;
      private       String              updatedBy;
      private       Date                createTime;
      private       Date                updateTime;
      private       Long                version;
      private       String              name;
      private       String              description;
      private       String              typeVersion;
      private       String              serviceType;
      private       Map<String, String> options;
  
      protected AtlasBaseTypeDef(TypeCategory category, String name, String description, String typeVersion, String serviceType, Map<String, String> options) {
          super();
  
          this.category = category;
  
          setGuid(null);
          setCreatedBy(null);
          setUpdatedBy(null);
          setCreateTime(null);
          setUpdateTime(null);
          setVersion(null);
          setName(name);
          setDescription(description);
          setTypeVersion(typeVersion);
          setServiceType(serviceType);
          setOptions(options);
      }
  
      protected AtlasBaseTypeDef(AtlasBaseTypeDef other) {
          if (other != null) {
              this.category = other.category;
  
              setGuid(other.getGuid());
              setCreatedBy(other.getCreatedBy());
              setUpdatedBy(other.getUpdatedBy());
              setCreateTime(other.getCreateTime());
              setUpdateTime(other.getUpdateTime());
              setVersion(other.getVersion());
              setName(other.getName());
              setServiceType(other.getServiceType());
              setDescription(other.getDescription());
              setTypeVersion(other.getTypeVersion());
              setOptions(other.getOptions());
          } else {
              this.category = TypeCategory.PRIMITIVE;
  
              setGuid(null);
              setCreatedBy(null);
              setUpdatedBy(null);
              setCreateTime(null);
              setUpdateTime(null);
              setVersion(null);
              setName(null);
              setServiceType(null);
              setDescription(null);
              setTypeVersion(null);
              setOptions(null);
          }
      }
  
      public static DateFormat getDateFormatter() {
          return THREAD_LOCAL_DATE_FORMAT.get();
      }
  
      public static String getArrayTypeName(String elemTypeName) {
          return ATLAS_TYPE_ARRAY_PREFIX + elemTypeName + ATLAS_TYPE_ARRAY_SUFFIX;
      }
  
      public static String getMapTypeName(String keyTypeName, String valueTypeName) {
          return String.format("%s%s%s%s%s", ATLAS_TYPE_MAP_PREFIX, keyTypeName, ATLAS_TYPE_MAP_KEY_VAL_SEP,
                  valueTypeName, ATLAS_TYPE_MAP_SUFFIX);
      }
  
      public static StringBuilder dumpObjects(Collection<?> objects, StringBuilder sb) {
          if (sb == null) {
              sb = new StringBuilder();
          }
  
          if (CollectionUtils.isNotEmpty(objects)) {
              int i = 0;
              for (Object obj : objects) {
                  if (i > 0) {
                      sb.append(", ");
                  }
  
                  sb.append(obj);
                  i++;
              }
          }
  
          return sb;
      }
  
      public static StringBuilder dumpObjects(Map<?, ?> objects, StringBuilder sb) {
          if (sb == null) {
              sb = new StringBuilder();
          }
  
          if (MapUtils.isNotEmpty(objects)) {
              int i = 0;
              for (Map.Entry<?, ?> e : objects.entrySet()) {
                  if (i > 0) {
                      sb.append(", ");
                  }
  
                  sb.append(e.getKey()).append(":").append(e.getValue());
                  i++;
              }
          }
  
          return sb;
      }
  
      public static StringBuilder dumpDateField(String prefix, Date value, StringBuilder sb) {
          sb.append(prefix);
  
          if (value == null) {
              sb.append(value);
          } else {
              sb.append(getDateFormatter().format(value));
          }
  
          return sb;
      }
  
      public TypeCategory getCategory() {
          return category;
      }
  
      public String getGuid() {
          return guid;
      }
  
      public void setGuid(String guid) {
          this.guid = guid;
      }
  
      public String getCreatedBy() {
          return createdBy;
      }
  
      public void setCreatedBy(String createdBy) {
          this.createdBy = createdBy;
      }
  
      public String getUpdatedBy() {
          return updatedBy;
      }
  
      public void setUpdatedBy(String updatedBy) {
          this.updatedBy = updatedBy;
      }
  
      public Date getCreateTime() {
          return createTime;
      }
  
      public void setCreateTime(Date createTime) {
          this.createTime = createTime;
      }
  
      public Date getUpdateTime() {
          return updateTime;
      }
  
      public void setUpdateTime(Date updateTime) {
          this.updateTime = updateTime;
      }
  
      public Long getVersion() {
          return version;
      }
  
      public void setVersion(Long version) {
          this.version = version;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          this.description = description;
      }
  
      public String getTypeVersion() {
          return typeVersion;
      }
  
      public void setTypeVersion(String typeVersion) {
          this.typeVersion = typeVersion;
      }
  
      public String getServiceType() {
          return serviceType;
      }
  
      public void setServiceType(String serviceType) {
          this.serviceType = serviceType;
      }
  
      public Map<String, String> getOptions() {
          return options;
      }
  
      public void setOptions(Map<String, String> options) {
          if (options != null) {
              this.options = new HashMap<>(options);
          } else {
              this.options = null;
          }
      }
  
      @JsonIgnore
      public String getOption(String optionName) {
          Map<String, String> options = this.options;
  
          return options != null ? options.get(optionName) : null;
      }
  
      @JsonIgnore
      public void setOption(String optionName, String value) {
          Map<String, String> options = this.options;
  
          if (options == null) {
              options      = new HashMap<>();
              this.options = options;
          }
  
          options.put(optionName, value);
      }
  
      public StringBuilder toString(StringBuilder sb) {
          if (sb == null) {
              sb = new StringBuilder();
          }
  
          sb.append("AtlasBaseTypeDef{");
          sb.append("category='").append(category).append('\'');
          sb.append(", guid='").append(guid).append('\'');
          sb.append(", createdBy='").append(createdBy).append('\'');
          sb.append(", updatedBy='").append(updatedBy).append('\'');
          dumpDateField(", createTime=", createTime, sb);
          dumpDateField(", updateTime=", updateTime, sb);
          sb.append(", version=").append(version);
          sb.append(", name='").append(name).append('\'');
          sb.append(", description='").append(description).append('\'');
          sb.append(", typeVersion='").append(typeVersion).append('\'');
          sb.append(", serviceType='").append(serviceType).append('\'');
          sb.append(", options='").append(options).append('\'');
          sb.append('}');
  
          return sb;
      }
  
      @Override
      public int hashCode() {
          return Objects.hash(category, guid, createdBy, updatedBy, createTime, updateTime, version, name, description, typeVersion, serviceType, options);
      }
  
      @Override
      public boolean equals(Object o) {
          if (this == o) {
              return true;
          } else if (o == null || getClass() != o.getClass()) {
              return false;
          }
  
          AtlasBaseTypeDef that = (AtlasBaseTypeDef) o;
  
          return category == that.category &&
                  Objects.equals(guid, that.guid) &&
                  Objects.equals(createdBy, that.createdBy) &&
                  Objects.equals(updatedBy, that.updatedBy) &&
                  Objects.equals(createTime, that.createTime) &&
                  Objects.equals(updateTime, that.updateTime) &&
                  Objects.equals(version, that.version) &&
                  Objects.equals(name, that.name) &&
                  Objects.equals(description, that.description) &&
                  Objects.equals(typeVersion, that.typeVersion) &&
                  Objects.equals(serviceType, that.serviceType) &&
                  Objects.equals(options, that.options);
      }
  
      static {
          DATE_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
      }
  }
  