You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sh...@apache.org on 2016/05/20 06:17:31 UTC
incubator-atlas git commit: ATLAS-683 Refactor local type-system
cache with cache provider interface (vmadugun via shwethags)
Repository: incubator-atlas
Updated Branches:
refs/heads/master 440bd2ae4 -> 5f248157b
ATLAS-683 Refactor local type-system cache with cache provider interface (vmadugun via shwethags)
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/5f248157
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/5f248157
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/5f248157
Branch: refs/heads/master
Commit: 5f248157bcb7daec1db66afe8d05f52f791296bc
Parents: 440bd2a
Author: Shwetha GS <ss...@hortonworks.com>
Authored: Fri May 20 11:44:07 2016 +0530
Committer: Shwetha GS <ss...@hortonworks.com>
Committed: Fri May 20 11:47:18 2016 +0530
----------------------------------------------------------------------
.gitignore | 2 +
.../org/apache/atlas/ApplicationProperties.java | 15 +-
distro/src/conf/atlas-application.properties | 5 +
release-log.txt | 1 +
.../apache/atlas/RepositoryMetadataModule.java | 8 +-
.../atlas/typesystem/types/TypeSystem.java | 200 ++++++----
.../types/cache/DefaultTypeCacheProvider.java | 229 +++++++++++
.../types/cache/ITypeCacheProvider.java | 137 +++++++
.../apache/atlas/ApplicationPropertiesTest.java | 14 +-
.../atlas/typesystem/types/TypeSystemTest.java | 2 +-
.../cache/DefaultTypeCacheProviderTest.java | 383 +++++++++++++++++++
11 files changed, 912 insertions(+), 84 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index f5899e2..0086a69 100755
--- a/.gitignore
+++ b/.gitignore
@@ -60,7 +60,9 @@ distro/hbase/*.tar.gz
#solr package downloaded
distro/solr/*.tgz
+# Scala-IDE specific
.cache-main
+.cache-tests
# emacs files
*#
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/common/src/main/java/org/apache/atlas/ApplicationProperties.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/atlas/ApplicationProperties.java b/common/src/main/java/org/apache/atlas/ApplicationProperties.java
index 6a4dca3..877d7db 100644
--- a/common/src/main/java/org/apache/atlas/ApplicationProperties.java
+++ b/common/src/main/java/org/apache/atlas/ApplicationProperties.java
@@ -92,13 +92,22 @@ public final class ApplicationProperties extends PropertiesConfiguration {
return inConf.subset(prefix);
}
- public static Class getClass(String propertyName, String defaultValue) {
+ public static Class getClass(String propertyName, String defaultValue, Class assignableClass)
+ throws AtlasException {
try {
Configuration configuration = get();
String propertyValue = configuration.getString(propertyName, defaultValue);
- return Class.forName(propertyValue);
+ Class<?> clazz = Class.forName(propertyValue);
+ if (assignableClass == null || assignableClass.isAssignableFrom(clazz)) {
+ return clazz;
+ } else {
+ String message = "Class " + clazz.getName() + " specified in property " + propertyName
+ + " is not assignable to class " + assignableClass.getName();
+ LOG.error(message);
+ throw new AtlasException(message);
+ }
} catch (Exception e) {
- throw new RuntimeException(e);
+ throw new AtlasException(e);
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/distro/src/conf/atlas-application.properties
----------------------------------------------------------------------
diff --git a/distro/src/conf/atlas-application.properties b/distro/src/conf/atlas-application.properties
index d4722fb..e2082ef 100755
--- a/distro/src/conf/atlas-application.properties
+++ b/distro/src/conf/atlas-application.properties
@@ -122,3 +122,8 @@ atlas.login.credentials.file=${sys:atlas.home}/conf/users-credentials.properties
#########POLICY FILE PATH #########
atlas.auth.policy.file=${sys:atlas.home}/conf/policy-store.txt
+######### Type Cache Provider Implementation ########
+# A type cache provider class which implements
+# org.apache.atlas.typesystem.types.cache.ITypeCacheProvider.
+# The default is DefaultTypeCacheProvider which is a local in-memory type cache.
+#atlas.typesystem.cache.provider=
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index c44ad0b..4a9a34d 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -21,6 +21,7 @@ ATLAS-409 Atlas will not import avro tables with schema read from a file (dosset
ATLAS-379 Create sqoop and falcon metadata addons (venkatnrangan,bvellanki,sowmyaramesh via shwethags)
ALL CHANGES:
+ATLAS-683 Refactor local type-system cache with cache provider interface (vmadugun via shwethags)
ATLAS-802 New look UI to show Business Catalog functionalities (kevalbhatt18 via yhemanth)
ATLAS-658 Improve Lineage with Backbone porting (kevalbhatt18 via yhemanth)
ATLAS-491 Business Catalog / Taxonomy (jspeidel via yhemanth)
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java b/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
index 68b707f..15201dd 100755
--- a/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
+++ b/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
@@ -111,7 +111,11 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
private static final String DELETE_HANDLER_IMPLEMENTATION_PROPERTY = "atlas.DeleteHandler.impl";
private Class<? extends DeleteHandler> getDeleteHandler() {
- return ApplicationProperties.getClass(DELETE_HANDLER_IMPLEMENTATION_PROPERTY,
- SoftDeleteHandler.class.getName());
+ try {
+ return ApplicationProperties.getClass(DELETE_HANDLER_IMPLEMENTATION_PROPERTY,
+ SoftDeleteHandler.class.getName(), DeleteHandler.class);
+ } catch (AtlasException e) {
+ throw new RuntimeException(e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/typesystem/src/main/java/org/apache/atlas/typesystem/types/TypeSystem.java
----------------------------------------------------------------------
diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/types/TypeSystem.java b/typesystem/src/main/java/org/apache/atlas/typesystem/types/TypeSystem.java
index 7763ebc..14f1968 100755
--- a/typesystem/src/main/java/org/apache/atlas/typesystem/types/TypeSystem.java
+++ b/typesystem/src/main/java/org/apache/atlas/typesystem/types/TypeSystem.java
@@ -18,19 +18,6 @@
package org.apache.atlas.typesystem.types;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import org.apache.atlas.AtlasException;
-import org.apache.atlas.classification.InterfaceAudience;
-import org.apache.atlas.typesystem.TypesDef;
-import org.apache.atlas.typesystem.exception.TypeExistsException;
-import org.apache.atlas.typesystem.exception.TypeNotFoundException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Singleton;
import java.lang.reflect.Constructor;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -41,10 +28,27 @@ import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
+import javax.inject.Singleton;
+
+import org.apache.atlas.ApplicationProperties;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.classification.InterfaceAudience;
+import org.apache.atlas.typesystem.TypesDef;
+import org.apache.atlas.typesystem.exception.TypeExistsException;
+import org.apache.atlas.typesystem.exception.TypeNotFoundException;
+import org.apache.atlas.typesystem.types.cache.DefaultTypeCacheProvider;
+import org.apache.atlas.typesystem.types.cache.ITypeCacheProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
@Singleton
@InterfaceAudience.Private
public class TypeSystem {
private static final Logger LOG = LoggerFactory.getLogger(TypeSystem.class);
+ private static final String CACHE_PROVIDER_CLASS_PROPERTY = "atlas.typesystem.cache.provider";
private static final TypeSystem INSTANCE = new TypeSystem();
private static ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>() {
@@ -56,15 +60,9 @@ public class TypeSystem {
}
};
- private Map<String, IDataType> types;
+ private ITypeCacheProvider typeCache;
private IdType idType;
-
- /**
- * An in-memory copy of type categories vs types for convenience.
- */
- private Multimap<DataTypes.TypeCategory, String> typeCategoriesToTypeNamesMap;
-
- private ImmutableList<String> coreTypes;
+ private Map<String, IDataType> coreTypes;
public TypeSystem() {
initialize();
@@ -78,69 +76,111 @@ public class TypeSystem {
* This is only used for testing purposes. Not intended for public use.
*/
@InterfaceAudience.Private
- public void reset() {
+ public TypeSystem reset() {
+
+ typeCache.clear(); // clear all entries in cache
initialize();
+
+ return this;
}
private void initialize() {
- types = new ConcurrentHashMap<>();
- typeCategoriesToTypeNamesMap = ArrayListMultimap.create(DataTypes.TypeCategory.values().length, 10);
+
+ initCacheProvider();
+ coreTypes = new ConcurrentHashMap<>();
registerPrimitiveTypes();
registerCoreTypes();
- coreTypes = ImmutableList.copyOf(types.keySet());
+ }
+
+ /**
+ * Ideally a cache provider should have been injected in the TypeSystemProvider,
+ * but a singleton of TypeSystem is constructed privately within the class so that
+ * clients of TypeSystem would never instantiate a TypeSystem object directly in
+ * their code. As soon as a client makes a call to TypeSystem.getInstance(), they
+ * should have the singleton ready for consumption. To enable such an access pattern,
+ * it kind of becomes imperative to initialize the cache provider within the
+ * TypeSystem constructor (bypassing the GUICE way of injecting a cache provider)
+ */
+ private void initCacheProvider() {
+
+ // read the pluggable cache provider from Atlas configuration
+ final String defaultCacheProvider = DefaultTypeCacheProvider.class.getName();
+ Class cacheProviderClass;
+ try {
+ cacheProviderClass = ApplicationProperties.getClass(CACHE_PROVIDER_CLASS_PROPERTY,
+ defaultCacheProvider, ITypeCacheProvider.class);
+ } catch (AtlasException e) {
+ throw new RuntimeException("Error getting type cache provider implementation class", e);
+ }
+
+ try {
+ typeCache = (ITypeCacheProvider)cacheProviderClass.newInstance();
+ }
+ catch (Exception e) {
+ throw new RuntimeException("Error creating instance of type cache provider implementation class " + cacheProviderClass.getName(), e);
+ }
}
public ImmutableList<String> getCoreTypes() {
- return coreTypes;
+ return ImmutableList.copyOf(coreTypes.keySet());
}
- public ImmutableList<String> getTypeNames() {
- List<String> typeNames = new ArrayList<>(types.keySet());
- typeNames.removeAll(getCoreTypes());
+ public ImmutableList<String> getTypeNames() throws AtlasException {
+ List<String> typeNames = new ArrayList<>(typeCache.getAllTypeNames());
return ImmutableList.copyOf(typeNames);
}
- public ImmutableList<String> getTypeNamesByCategory(DataTypes.TypeCategory typeCategory) {
- return ImmutableList.copyOf(typeCategoriesToTypeNamesMap.get(typeCategory));
+ public ImmutableList<String> getTypeNamesByCategory(DataTypes.TypeCategory typeCategory) throws AtlasException {
+ return ImmutableList.copyOf(typeCache.getTypeNames(typeCategory));
}
private void registerPrimitiveTypes() {
- types.put(DataTypes.BOOLEAN_TYPE.getName(), DataTypes.BOOLEAN_TYPE);
- types.put(DataTypes.BYTE_TYPE.getName(), DataTypes.BYTE_TYPE);
- types.put(DataTypes.SHORT_TYPE.getName(), DataTypes.SHORT_TYPE);
- types.put(DataTypes.INT_TYPE.getName(), DataTypes.INT_TYPE);
- types.put(DataTypes.LONG_TYPE.getName(), DataTypes.LONG_TYPE);
- types.put(DataTypes.FLOAT_TYPE.getName(), DataTypes.FLOAT_TYPE);
- types.put(DataTypes.DOUBLE_TYPE.getName(), DataTypes.DOUBLE_TYPE);
- types.put(DataTypes.BIGINTEGER_TYPE.getName(), DataTypes.BIGINTEGER_TYPE);
- types.put(DataTypes.BIGDECIMAL_TYPE.getName(), DataTypes.BIGDECIMAL_TYPE);
- types.put(DataTypes.DATE_TYPE.getName(), DataTypes.DATE_TYPE);
- types.put(DataTypes.STRING_TYPE.getName(), DataTypes.STRING_TYPE);
- typeCategoriesToTypeNamesMap.putAll(DataTypes.TypeCategory.PRIMITIVE, types.keySet());
+ coreTypes.put(DataTypes.BOOLEAN_TYPE.getName(), DataTypes.BOOLEAN_TYPE);
+ coreTypes.put(DataTypes.BYTE_TYPE.getName(), DataTypes.BYTE_TYPE);
+ coreTypes.put(DataTypes.SHORT_TYPE.getName(), DataTypes.SHORT_TYPE);
+ coreTypes.put(DataTypes.INT_TYPE.getName(), DataTypes.INT_TYPE);
+ coreTypes.put(DataTypes.LONG_TYPE.getName(), DataTypes.LONG_TYPE);
+ coreTypes.put(DataTypes.FLOAT_TYPE.getName(), DataTypes.FLOAT_TYPE);
+ coreTypes.put(DataTypes.DOUBLE_TYPE.getName(), DataTypes.DOUBLE_TYPE);
+ coreTypes.put(DataTypes.BIGINTEGER_TYPE.getName(), DataTypes.BIGINTEGER_TYPE);
+ coreTypes.put(DataTypes.BIGDECIMAL_TYPE.getName(), DataTypes.BIGDECIMAL_TYPE);
+ coreTypes.put(DataTypes.DATE_TYPE.getName(), DataTypes.DATE_TYPE);
+ coreTypes.put(DataTypes.STRING_TYPE.getName(), DataTypes.STRING_TYPE);
}
-
/*
* The only core OOB type we will define is the Struct to represent the Identity of an Instance.
*/
private void registerCoreTypes() {
+
idType = new IdType();
+ coreTypes.put(idType.getStructType().getName(), idType.getStructType());
}
public IdType getIdType() {
return idType;
}
- public boolean isRegistered(String typeName) {
- return types.containsKey(typeName);
+ public boolean isRegistered(String typeName) throws AtlasException {
+ return isCoreType(typeName) || typeCache.has(typeName);
+ }
+
+ protected boolean isCoreType(String typeName) {
+
+ return coreTypes.containsKey(typeName);
}
public <T> T getDataType(Class<T> cls, String name) throws AtlasException {
- if (types.containsKey(name)) {
+
+ if (isCoreType(name)) {
+ return cls.cast(coreTypes.get(name));
+ }
+
+ if (typeCache.has(name)) {
try {
- return cls.cast(types.get(name));
+ return cls.cast(typeCache.get(name));
} catch (ClassCastException cce) {
throw new AtlasException(cce);
}
@@ -285,13 +325,12 @@ public class TypeSystem {
public EnumType defineEnumType(EnumTypeDefinition eDef) throws AtlasException {
assert eDef.name != null;
- if (types.containsKey(eDef.name)) {
+ if (isRegistered(eDef.name)) {
throw new AtlasException(String.format("Redefinition of type %s not supported", eDef.name));
}
EnumType eT = new EnumType(this, eDef.name, eDef.description, eDef.enumValues);
- types.put(eDef.name, eT);
- typeCategoriesToTypeNamesMap.put(DataTypes.TypeCategory.ENUM, eDef.name);
+ typeCache.put(eT);
return eT;
}
@@ -329,17 +368,14 @@ public class TypeSystem {
*
* This step should be called only after the types have been committed to the backend stores successfully.
* @param typesAdded newly added types.
+ * @throws AtlasException
*/
- public void commitTypes(Map<String, IDataType> typesAdded) {
+ public void commitTypes(Map<String, IDataType> typesAdded) throws AtlasException {
for (Map.Entry<String, IDataType> typeEntry : typesAdded.entrySet()) {
String typeName = typeEntry.getKey();
IDataType type = typeEntry.getValue();
//Add/replace the new type in the typesystem
- types.put(typeName, type);
- // ArrayListMultiMap allows duplicates - we want to avoid this during re-activation.
- if (!typeCategoriesToTypeNamesMap.containsEntry(type.getTypeCategory(), typeName)) {
- typeCategoriesToTypeNamesMap.put(type.getTypeCategory(), typeName);
- }
+ typeCache.put(type);
}
}
@@ -372,10 +408,12 @@ public class TypeSystem {
}
private IDataType dataType(String name) throws AtlasException {
+
if (transientTypes.containsKey(name)) {
return transientTypes.get(name);
}
- return TypeSystem.this.types.get(name);
+
+ return TypeSystem.this.getDataType(IDataType.class, name);
}
/*
@@ -386,7 +424,7 @@ public class TypeSystem {
private void validateAndSetupShallowTypes(boolean update) throws AtlasException {
for (EnumTypeDefinition eDef : enumDefs) {
assert eDef.name != null;
- if (!update && (transientTypes.containsKey(eDef.name) || types.containsKey(eDef.name))) {
+ if (!update && (transientTypes.containsKey(eDef.name) || isRegistered(eDef.name))) {
throw new AtlasException(String.format("Redefinition of type %s not supported", eDef.name));
}
@@ -396,7 +434,7 @@ public class TypeSystem {
for (StructTypeDefinition sDef : structDefs) {
assert sDef.typeName != null;
- if (!update && (transientTypes.containsKey(sDef.typeName) || types.containsKey(sDef.typeName))) {
+ if (!update && (transientTypes.containsKey(sDef.typeName) || isRegistered(sDef.typeName))) {
throw new TypeExistsException(String.format("Cannot redefine type %s", sDef.typeName));
}
StructType sT = new StructType(this, sDef.typeName, sDef.typeDescription, sDef.attributeDefinitions.length);
@@ -407,7 +445,7 @@ public class TypeSystem {
for (HierarchicalTypeDefinition<TraitType> traitDef : traitDefs) {
assert traitDef.typeName != null;
if (!update &&
- (transientTypes.containsKey(traitDef.typeName) || types.containsKey(traitDef.typeName))) {
+ (transientTypes.containsKey(traitDef.typeName) || isRegistered(traitDef.typeName))) {
throw new TypeExistsException(String.format("Cannot redefine type %s", traitDef.typeName));
}
TraitType tT = new TraitType(this, traitDef.typeName, traitDef.typeDescription, traitDef.superTypes,
@@ -419,7 +457,7 @@ public class TypeSystem {
for (HierarchicalTypeDefinition<ClassType> classDef : classDefs) {
assert classDef.typeName != null;
if (!update &&
- (transientTypes.containsKey(classDef.typeName) || types.containsKey(classDef.typeName))) {
+ (transientTypes.containsKey(classDef.typeName) || isRegistered(classDef.typeName))) {
throw new TypeExistsException(String.format("Cannot redefine type %s", classDef.typeName));
}
@@ -582,11 +620,11 @@ public class TypeSystem {
* Step 5:
* - Validate that the update can be done
*/
- private void validateUpdateIsPossible() throws TypeUpdateException {
+ private void validateUpdateIsPossible() throws TypeUpdateException, AtlasException {
//If the type is modified, validate that update can be done
for (IDataType newType : transientTypes.values()) {
- if (TypeSystem.this.types.containsKey(newType.getName())) {
- IDataType oldType = TypeSystem.this.types.get(newType.getName());
+ if (TypeSystem.this.isRegistered(newType.getName())) {
+ IDataType oldType = TypeSystem.this.typeCache.get(newType.getName());
oldType.validateUpdate(newType);
}
}
@@ -600,7 +638,7 @@ public class TypeSystem {
}
@Override
- public ImmutableList<String> getTypeNames() {
+ public ImmutableList<String> getTypeNames() throws AtlasException {
Set<String> typeNames = transientTypes.keySet();
typeNames.addAll(TypeSystem.this.getTypeNames());
return ImmutableList.copyOf(typeNames);
@@ -644,17 +682,17 @@ public class TypeSystem {
@Override
public StructType defineStructType(String name, boolean errorIfExists, AttributeDefinition... attrDefs)
throws AtlasException {
- throw new AtlasException("Internal Error: define type called on TrasientTypeSystem");
+ throw new AtlasException("Internal Error: define type called on TransientTypeSystem");
}
@Override
public TraitType defineTraitType(HierarchicalTypeDefinition traitDef) throws AtlasException {
- throw new AtlasException("Internal Error: define type called on TrasientTypeSystem");
+ throw new AtlasException("Internal Error: define type called on TransientTypeSystem");
}
@Override
public ClassType defineClassType(HierarchicalTypeDefinition<ClassType> classDef) throws AtlasException {
- throw new AtlasException("Internal Error: define type called on TrasientTypeSystem");
+ throw new AtlasException("Internal Error: define type called on TransientTypeSystem");
}
@Override
@@ -662,7 +700,7 @@ public class TypeSystem {
ImmutableList<StructTypeDefinition> structDefs,
ImmutableList<HierarchicalTypeDefinition<TraitType>> traitDefs,
ImmutableList<HierarchicalTypeDefinition<ClassType>> classDefs) throws AtlasException {
- throw new AtlasException("Internal Error: define type called on TrasientTypeSystem");
+ throw new AtlasException("Internal Error: define type called on TransientTypeSystem");
}
@Override
@@ -686,13 +724,22 @@ public class TypeSystem {
}
@Override
- public void commitTypes(Map<String, IDataType> typesAdded) {
+ public void commitTypes(Map<String, IDataType> typesAdded) throws AtlasException {
TypeSystem.this.commitTypes(typesAdded);
}
public Map<String, IDataType> getTypesAdded() {
return new HashMap<>(transientTypes);
}
+
+ /**
+ * The core types do not change and they are registered
+ * once in the main type system.
+ */
+ @Override
+ public ImmutableList<String> getCoreTypes() {
+ return TypeSystem.this.getCoreTypes();
+ }
}
public class IdType {
@@ -700,6 +747,8 @@ public class TypeSystem {
private static final String TYPENAME_ATTRNAME = "typeName";
private static final String TYP_NAME = "__IdType";
+ private StructType type;
+
private IdType() {
AttributeDefinition idAttr =
new AttributeDefinition(ID_ATTRNAME, DataTypes.STRING_TYPE.getName(), Multiplicity.REQUIRED, false,
@@ -712,16 +761,14 @@ public class TypeSystem {
infos[0] = new AttributeInfo(TypeSystem.this, idAttr, null);
infos[1] = new AttributeInfo(TypeSystem.this, typNmAttr, null);
- StructType type = new StructType(TypeSystem.this, TYP_NAME, null, infos);
- TypeSystem.this.types.put(TYP_NAME, type);
-
+ type = new StructType(TypeSystem.this, TYP_NAME, null, infos);
} catch (AtlasException me) {
throw new RuntimeException(me);
}
}
- public StructType getStructType() throws AtlasException {
- return getDataType(StructType.class, TYP_NAME);
+ public StructType getStructType() {
+ return type;
}
public String getName() {
@@ -738,4 +785,5 @@ public class TypeSystem {
}
public static final String ID_STRUCT_ID_ATTRNAME = IdType.ID_ATTRNAME;
+ public static final String ID_STRUCT_TYP_NAME = IdType.TYP_NAME;
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProvider.java
----------------------------------------------------------------------
diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProvider.java b/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProvider.java
new file mode 100644
index 0000000..700bda6
--- /dev/null
+++ b/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProvider.java
@@ -0,0 +1,229 @@
+/**
+ * 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
+ *
+ * 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 org.apache.atlas.typesystem.types.cache;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.typesystem.types.ClassType;
+import org.apache.atlas.typesystem.types.DataTypes.TypeCategory;
+import org.apache.atlas.typesystem.types.EnumType;
+import org.apache.atlas.typesystem.types.IDataType;
+import org.apache.atlas.typesystem.types.StructType;
+import org.apache.atlas.typesystem.types.TraitType;
+
+import com.google.inject.Singleton;
+
+/**
+ * Caches the types in-memory within the same process space.
+ */
+@Singleton
+@SuppressWarnings("rawtypes")
+public class DefaultTypeCacheProvider implements ITypeCacheProvider {
+
+ private Map<String, IDataType> types_ = new ConcurrentHashMap<>();
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#has(java.lang
+ * .String)
+ */
+ @Override
+ public boolean has(String typeName) throws AtlasException {
+
+ return types_.containsKey(typeName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#has(org.
+ * apache.atlas.typesystem.types.DataTypes.TypeCategory, java.lang.String)
+ */
+ @Override
+ public boolean has(TypeCategory typeCategory, String typeName)
+ throws AtlasException {
+
+ assertValidTypeCategory(typeCategory);
+ return has(typeName);
+ }
+
+ private void assertValidTypeCategory(TypeCategory typeCategory) throws
+ AtlasException {
+
+ // there might no need of 'typeCategory' in this implementation for
+ // certain API, but for a distributed cache, it might help for the
+ // implementers to partition the types per their category
+ // while persisting so that look can be efficient
+
+ if (typeCategory == null) {
+ throw new AtlasException("Category of the types to be filtered is null.");
+ }
+
+ boolean validTypeCategory = typeCategory.equals(TypeCategory.CLASS) ||
+ typeCategory.equals(TypeCategory.TRAIT) ||
+ typeCategory.equals(TypeCategory.ENUM) ||
+ typeCategory.equals(TypeCategory.STRUCT);
+
+ if (!validTypeCategory) {
+ throw new AtlasException("Category of the types should be one of CLASS "
+ + "| TRAIT | ENUM | STRUCT.");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#get(java.lang
+ * .String)
+ */
+ @Override
+ public IDataType get(String typeName) throws AtlasException {
+
+ return types_.get(typeName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#get(org.apache.
+ * atlas.typesystem.types.DataTypes.TypeCategory, java.lang.String)
+ */
+ @Override
+ public IDataType get(TypeCategory typeCategory, String typeName) throws AtlasException {
+
+ assertValidTypeCategory(typeCategory);
+ return get(typeName);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#getNames(org
+ * .apache.atlas.typesystem.types.DataTypes.TypeCategory)
+ */
+ @Override
+ public Collection<String> getTypeNames(TypeCategory typeCategory) throws AtlasException {
+
+ assertValidTypeCategory(typeCategory);
+
+ List<String> typeNames = new ArrayList<>();
+ for (Entry<String, IDataType> typeEntry : types_.entrySet()) {
+ String name = typeEntry.getKey();
+ IDataType type = typeEntry.getValue();
+
+ if (type.getTypeCategory().equals(typeCategory)) {
+ typeNames.add(name);
+ }
+ }
+ return typeNames;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#getAllNames()
+ */
+ @Override
+ public Collection<String> getAllTypeNames() throws AtlasException {
+
+ return types_.keySet();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#put(org.apache
+ * .atlas.typesystem.types.IDataType)
+ */
+ @Override
+ public void put(IDataType type) throws AtlasException {
+
+ assertValidType(type);
+ types_.put(type.getName(), type);
+ }
+
+ private void assertValidType(IDataType type) throws
+ AtlasException {
+
+ if (type == null) {
+ throw new AtlasException("type is null.");
+ }
+
+ boolean validTypeCategory = (type instanceof ClassType) ||
+ (type instanceof TraitType) ||
+ (type instanceof EnumType) ||
+ (type instanceof StructType);
+
+ if (!validTypeCategory) {
+ throw new AtlasException("Category of the types should be one of ClassType | "
+ + "TraitType | EnumType | StructType.");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#putAll(java
+ * .util.Collection)
+ */
+ @Override
+ public void putAll(Collection<IDataType> types) throws AtlasException {
+
+ for (IDataType type : types) {
+ assertValidType(type);
+ types_.put(type.getName(), type);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#remove(java
+ * .lang.String)
+ */
+ @Override
+ public void remove(String typeName) throws AtlasException {
+
+ types_.remove(typeName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#remove(org.
+ * apache.atlas.typesystem.types.DataTypes.TypeCategory, java.lang.String)
+ */
+ @Override
+ public void remove(TypeCategory typeCategory, String typeName)
+ throws AtlasException {
+
+ assertValidTypeCategory(typeCategory);
+ remove(typeName);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.atlas.typesystem.types.cache.ITypeCacheProvider#clear()
+ */
+ @Override
+ public void clear() {
+
+ types_.clear();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/ITypeCacheProvider.java
----------------------------------------------------------------------
diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/ITypeCacheProvider.java b/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/ITypeCacheProvider.java
new file mode 100644
index 0000000..55e9ddc
--- /dev/null
+++ b/typesystem/src/main/java/org/apache/atlas/typesystem/types/cache/ITypeCacheProvider.java
@@ -0,0 +1,137 @@
+/**
+ * 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
+ *
+ * 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 org.apache.atlas.typesystem.types.cache;
+
+import java.util.Collection;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.typesystem.types.DataTypes;
+import org.apache.atlas.typesystem.types.IDataType;
+
+/**
+ * The types are cached to allow faster lookup when type info is needed during
+ * creation/updation of entities, DSL query translation/execution.
+ * Implementations of this can chose to plugin a distributed cache provider
+ * or an in-memory cache synched across nodes in an Altas cluster. <br>
+ * <br>
+ * Type entries in the cache can be one of ... <br>
+ * {@link org.apache.atlas.typesystem.types.ClassType} <br>
+ * {@link org.apache.atlas.typesystem.types.TraitType} <br>
+ * {@link org.apache.atlas.typesystem.types.StructType} <br>
+ * {@link org.apache.atlas.typesystem.types.EnumType}
+ */
+@SuppressWarnings("rawtypes")
+public interface ITypeCacheProvider {
+
+ /**
+ * @param typeName
+ * @return true if the type exists in cache, false otherwise.
+ * @throws AtlasException
+ */
+ boolean has(String typeName) throws AtlasException;
+
+ /**
+ * @param typeCategory Non-null category of type. The category can be one of
+ * TypeCategory.CLASS | TypeCategory.TRAIT | TypeCategory.STRUCT | TypeCategory.ENUM.
+ * @param typeName
+ * @return true if the type of given category exists in cache, false otherwise.
+ * @throws AtlasException
+ */
+ boolean has(DataTypes.TypeCategory typeCategory, String typeName) throws AtlasException;
+
+ /**
+ * @param name The name of the type.
+ * @return returns non-null type if cached, otherwise null
+ * @throws AtlasException
+ */
+ public IDataType get(String typeName) throws AtlasException;
+
+ /**
+ * @param typeCategory Non-null category of type. The category can be one of
+ * TypeCategory.CLASS | TypeCategory.TRAIT | TypeCategory.STRUCT | TypeCategory.ENUM.
+ * @param typeName
+ * @return returns non-null type (of the specified category) if cached, otherwise null
+ * @throws AtlasException
+ */
+ public IDataType get(DataTypes.TypeCategory typeCategory, String typeName) throws AtlasException;
+
+ /**
+ * @param typeCategory The category of types to filter the returned types. Cannot be null.
+ * The category can be one of TypeCategory.CLASS | TypeCategory.TRAIT |
+ * TypeCategory.STRUCT | TypeCategory.ENUM.
+ * @return
+ * @throws AtlasException
+ */
+ Collection<String> getTypeNames(DataTypes.TypeCategory typeCategory) throws AtlasException;
+
+ /**
+ * This is a convenience API to get the names of all types.
+ *
+ * @see ITypeCacheProvider#getTypeNames(org.apache.atlas.typesystem.types.DataTypes.TypeCategory)
+ * @return
+ * @throws AtlasException
+ */
+ Collection<String> getAllTypeNames() throws AtlasException;
+
+ /**
+ * @param type The type to be added to the cache. The type should not be
+ * null, otherwise throws NullPointerException. <br>
+ * Type entries in the cache can be one of ... <br>
+ * {@link org.apache.atlas.typesystem.types.ClassType} <br>
+ * {@link org.apache.atlas.typesystem.types.TraitType} <br>
+ * {@link org.apache.atlas.typesystem.types.StructType} <br>
+ * {@link org.apache.atlas.typesystem.types.EnumType}
+ * @throws AtlasException
+ */
+ void put(IDataType type) throws AtlasException;
+
+ /**
+ * @param types The types to be added to the cache. The type should not be
+ * null, otherwise throws NullPointerException. <br>
+ * Type entries in the cache can be one of ... <br>
+ * {@link org.apache.atlas.typesystem.types.ClassType} <br>
+ * {@link org.apache.atlas.typesystem.types.TraitType} <br>
+ * {@link org.apache.atlas.typesystem.types.StructType} <br>
+ * {@link org.apache.atlas.typesystem.types.EnumType}
+ * @throws AtlasException
+ */
+ void putAll(Collection<IDataType> types) throws AtlasException;
+
+ /**
+ * @param typeName Name of the type to be removed from the cache. If type
+ * exists, it will be removed, otherwise does nothing.
+ * @throws AtlasException
+ */
+ void remove(String typeName) throws AtlasException;
+
+ /**
+ * @param typeCategory Non-null category of type. The category can be one of
+ * TypeCategory.CLASS | TypeCategory.TRAIT | TypeCategory.STRUCT | TypeCategory.ENUM.
+ * @param typeName Name of the type to be removed from the cache. If type
+ * exists, it will be removed, otherwise does nothing.
+ * @throws AtlasException
+ */
+ void remove(DataTypes.TypeCategory typeCategory, String typeName) throws AtlasException;
+
+ /**
+ * Clear the type cache
+ *
+ */
+ void clear();
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/typesystem/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java
----------------------------------------------------------------------
diff --git a/typesystem/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java b/typesystem/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java
index 27f1f7e..0679642 100644
--- a/typesystem/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java
+++ b/typesystem/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java
@@ -19,6 +19,7 @@ package org.apache.atlas;
import org.apache.atlas.typesystem.types.TypeSystem;
import org.apache.commons.configuration.Configuration;
+import org.testng.Assert;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
@@ -58,11 +59,20 @@ public class ApplicationPropertiesTest {
@Test
public void testGetClass() throws Exception {
//read from atlas-application.properties
- Class cls = ApplicationProperties.getClass("atlas.TypeSystem.impl", ApplicationProperties.class.getName());
+ Class cls = ApplicationProperties.getClass("atlas.TypeSystem.impl", ApplicationProperties.class.getName(), TypeSystem.class);
assertEquals(cls.getName(), TypeSystem.class.getName());
//default value
- cls = ApplicationProperties.getClass("atlas.TypeSystem2.impl", TypeSystem.class.getName());
+ cls = ApplicationProperties.getClass("atlas.TypeSystem2.impl", TypeSystem.class.getName(), TypeSystem.class);
assertEquals(cls.getName(), TypeSystem.class.getName());
+
+ //incompatible assignTo class, should throw AtlasException
+ try {
+ cls = ApplicationProperties.getClass("atlas.TypeSystem.impl", ApplicationProperties.class.getName(), ApplicationProperties.class);
+ Assert.fail(AtlasException.class.getSimpleName() + " was expected but none thrown.");
+ }
+ catch (AtlasException e) {
+ // good
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/typesystem/src/test/java/org/apache/atlas/typesystem/types/TypeSystemTest.java
----------------------------------------------------------------------
diff --git a/typesystem/src/test/java/org/apache/atlas/typesystem/types/TypeSystemTest.java b/typesystem/src/test/java/org/apache/atlas/typesystem/types/TypeSystemTest.java
index c0574ce..574e0f9 100755
--- a/typesystem/src/test/java/org/apache/atlas/typesystem/types/TypeSystemTest.java
+++ b/typesystem/src/test/java/org/apache/atlas/typesystem/types/TypeSystemTest.java
@@ -209,7 +209,7 @@ public class TypeSystemTest extends BaseTest {
}
@Test
- public void testTypeNamesAreNotDuplicated() {
+ public void testTypeNamesAreNotDuplicated() throws Exception {
TypeSystem typeSystem = getTypeSystem();
ImmutableList<String> traitNames = typeSystem.getTypeNamesByCategory(DataTypes.TypeCategory.TRAIT);
int numTraits = traitNames.size();
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5f248157/typesystem/src/test/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProviderTest.java
----------------------------------------------------------------------
diff --git a/typesystem/src/test/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProviderTest.java b/typesystem/src/test/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProviderTest.java
new file mode 100644
index 0000000..c426d50
--- /dev/null
+++ b/typesystem/src/test/java/org/apache/atlas/typesystem/types/cache/DefaultTypeCacheProviderTest.java
@@ -0,0 +1,383 @@
+/**
+ * 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
+ *
+ * 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 org.apache.atlas.typesystem.types.cache;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.typesystem.types.ClassType;
+import org.apache.atlas.typesystem.types.DataTypes;
+import org.apache.atlas.typesystem.types.DataTypes.TypeCategory;
+import org.apache.atlas.typesystem.types.EnumType;
+import org.apache.atlas.typesystem.types.EnumValue;
+import org.apache.atlas.typesystem.types.IDataType;
+import org.apache.atlas.typesystem.types.StructType;
+import org.apache.atlas.typesystem.types.TraitType;
+import org.apache.atlas.typesystem.types.TypeSystem;
+import org.apache.atlas.typesystem.types.utils.TypesUtil;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests functional behavior of {@link DefaultTypeCacheProvider}
+ */
+@SuppressWarnings("rawtypes")
+public class DefaultTypeCacheProviderTest {
+
+ private String CLASSTYPE_CUSTOMER = "Customer";
+ private String STRUCTTYPE_ADDRESS = "Address";
+ private String TRAITTYPE_PRIVILEGED = "Privileged";
+ private String ENUMTYPE_SHIPPING = "Shipping";
+
+ private String UNKNOWN_TYPE = "UndefinedType";
+
+ private ClassType customerType;
+ private StructType addressType;
+ private TraitType privilegedTrait;
+ private EnumType shippingEnum;
+
+ private DefaultTypeCacheProvider cacheProvider;
+
+ @BeforeClass
+ public void onetimeSetup() throws Exception {
+
+ // init TypeSystem
+ TypeSystem ts = TypeSystem.getInstance().reset();
+
+ // Customer ClassType
+ customerType = ts.defineClassType(TypesUtil
+ .createClassTypeDef(CLASSTYPE_CUSTOMER, ImmutableSet.<String>of(),
+ TypesUtil.createRequiredAttrDef("name", DataTypes.STRING_TYPE),
+ TypesUtil.createRequiredAttrDef("id", DataTypes.LONG_TYPE)));
+
+ // Address StructType
+ addressType = ts.defineStructType(STRUCTTYPE_ADDRESS, true,
+ TypesUtil.createRequiredAttrDef("first line", DataTypes.STRING_TYPE),
+ TypesUtil.createOptionalAttrDef("second line", DataTypes.STRING_TYPE),
+ TypesUtil.createRequiredAttrDef("city", DataTypes.STRING_TYPE),
+ TypesUtil.createRequiredAttrDef("pincode", DataTypes.INT_TYPE));
+
+ // Privileged TraitType
+ privilegedTrait = ts.defineTraitType(TypesUtil
+ .createTraitTypeDef(TRAITTYPE_PRIVILEGED, ImmutableSet.<String>of(),
+ TypesUtil.createRequiredAttrDef("category", DataTypes.INT_TYPE)));
+
+ // Shipping EnumType
+ shippingEnum = ts.defineEnumType(TypesUtil.createEnumTypeDef(ENUMTYPE_SHIPPING,
+ new EnumValue("Domestic", 1), new EnumValue("International", 2)));
+ }
+
+ @BeforeMethod
+ public void eachTestSetup() throws Exception {
+
+ cacheProvider = new DefaultTypeCacheProvider();
+
+ cacheProvider.put(customerType);
+ cacheProvider.put(addressType);
+ cacheProvider.put(privilegedTrait);
+ cacheProvider.put(shippingEnum);
+ }
+
+ @Test
+ public void testCacheGetType() throws Exception {
+
+ IDataType custType = cacheProvider.get(CLASSTYPE_CUSTOMER);
+ verifyType(custType, CLASSTYPE_CUSTOMER, ClassType.class);
+
+ IDataType addrType = cacheProvider.get(STRUCTTYPE_ADDRESS);
+ verifyType(addrType, STRUCTTYPE_ADDRESS, StructType.class);
+
+ IDataType privTrait = cacheProvider.get(TRAITTYPE_PRIVILEGED);
+ verifyType(privTrait, TRAITTYPE_PRIVILEGED, TraitType.class);
+
+ IDataType shippingEnum = cacheProvider.get(ENUMTYPE_SHIPPING);
+ verifyType(shippingEnum, ENUMTYPE_SHIPPING, EnumType.class);
+
+ assertNull(cacheProvider.get(UNKNOWN_TYPE));
+ }
+
+ @Test
+ public void testCacheGetTypeByCategory() throws Exception {
+
+ IDataType custType = cacheProvider.get(TypeCategory.CLASS, CLASSTYPE_CUSTOMER);
+ verifyType(custType, CLASSTYPE_CUSTOMER, ClassType.class);
+
+ IDataType addrType = cacheProvider.get(TypeCategory.STRUCT, STRUCTTYPE_ADDRESS);
+ verifyType(addrType, STRUCTTYPE_ADDRESS, StructType.class);
+
+ IDataType privTrait = cacheProvider.get(TypeCategory.TRAIT, TRAITTYPE_PRIVILEGED);
+ verifyType(privTrait, TRAITTYPE_PRIVILEGED, TraitType.class);
+
+ IDataType shippingEnum = cacheProvider.get(TypeCategory.ENUM, ENUMTYPE_SHIPPING);
+ verifyType(shippingEnum, ENUMTYPE_SHIPPING, EnumType.class);
+
+ assertNull(cacheProvider.get(UNKNOWN_TYPE));
+ }
+
+ private void verifyType(IDataType actualType, String expectedName, Class<? extends IDataType> typeClass) {
+
+ assertNotNull(actualType, "The " + expectedName + " type not in cache");
+ assertTrue(typeClass.isInstance(actualType));
+ assertEquals(actualType.getName(), expectedName, "The type name does not match");
+ }
+
+ @Test
+ public void testCacheHasType() throws Exception {
+
+ assertTrue(cacheProvider.has(CLASSTYPE_CUSTOMER));
+ assertTrue(cacheProvider.has(STRUCTTYPE_ADDRESS));
+ assertTrue(cacheProvider.has(TRAITTYPE_PRIVILEGED));
+ assertTrue(cacheProvider.has(ENUMTYPE_SHIPPING));
+
+ assertFalse(cacheProvider.has(UNKNOWN_TYPE));
+ }
+
+ @Test
+ public void testCacheHasTypeByCategory() throws Exception {
+
+ assertTrue(cacheProvider.has(TypeCategory.CLASS, CLASSTYPE_CUSTOMER));
+ assertTrue(cacheProvider.has(TypeCategory.STRUCT, STRUCTTYPE_ADDRESS));
+ assertTrue(cacheProvider.has(TypeCategory.TRAIT, TRAITTYPE_PRIVILEGED));
+ assertTrue(cacheProvider.has(TypeCategory.ENUM, ENUMTYPE_SHIPPING));
+
+ assertFalse(cacheProvider.has(UNKNOWN_TYPE));
+ }
+
+ @Test
+ public void testCacheGetAllTypeNames() throws Exception {
+
+ List<String> allTypeNames = new ArrayList<String>(cacheProvider.getAllTypeNames());
+ Collections.sort(allTypeNames);
+
+ final int EXPECTED_TYPE_COUNT = 4;
+ assertEquals(allTypeNames.size(), EXPECTED_TYPE_COUNT, "Total number of types does not match.");
+
+ assertEquals(STRUCTTYPE_ADDRESS, allTypeNames.get(0));
+ assertEquals(CLASSTYPE_CUSTOMER, allTypeNames.get(1));
+ assertEquals(TRAITTYPE_PRIVILEGED, allTypeNames.get(2));
+ assertEquals(ENUMTYPE_SHIPPING, allTypeNames.get(3));
+ }
+
+ @Test
+ public void testCacheGetTypeNamesByCategory() throws Exception {
+
+ List<String> classTypes = new ArrayList<String>(cacheProvider.getTypeNames(TypeCategory.CLASS));
+ final int EXPECTED_CLASSTYPE_COUNT = 1;
+ assertEquals(classTypes.size(), EXPECTED_CLASSTYPE_COUNT);
+ assertEquals(CLASSTYPE_CUSTOMER, classTypes.get(0));
+
+ List<String> structTypes = new ArrayList<String>(cacheProvider.getTypeNames(TypeCategory.STRUCT));
+ final int EXPECTED_STRUCTTYPE_COUNT = 1;
+ assertEquals(structTypes.size(), EXPECTED_STRUCTTYPE_COUNT);
+ assertEquals(STRUCTTYPE_ADDRESS, structTypes.get(0));
+
+ List<String> traitTypes = new ArrayList<String>(cacheProvider.getTypeNames(TypeCategory.TRAIT));
+ final int EXPECTED_TRAITTYPE_COUNT = 1;
+ assertEquals(traitTypes.size(), EXPECTED_TRAITTYPE_COUNT);
+ assertEquals(TRAITTYPE_PRIVILEGED, traitTypes.get(0));
+
+ List<String> enumTypes = new ArrayList<String>(cacheProvider.getTypeNames(TypeCategory.ENUM));
+ final int EXPECTED_ENUMTYPE_COUNT = 1;
+ assertEquals(enumTypes.size(), EXPECTED_ENUMTYPE_COUNT);
+ assertEquals(ENUMTYPE_SHIPPING, enumTypes.get(0));
+ }
+
+ @Test
+ public void testCacheBulkInsert() throws Exception {
+
+ List<IDataType> allTypes = new ArrayList<>();
+ allTypes.add(customerType);
+ allTypes.add(addressType);
+ allTypes.add(privilegedTrait);
+ allTypes.add(shippingEnum);
+
+ // create a new cache provider instead of using the one setup for every method call
+ cacheProvider = new DefaultTypeCacheProvider();
+ cacheProvider.putAll(allTypes);
+
+ IDataType custType = cacheProvider.get(CLASSTYPE_CUSTOMER);
+ verifyType(custType, CLASSTYPE_CUSTOMER, ClassType.class);
+
+ IDataType addrType = cacheProvider.get(STRUCTTYPE_ADDRESS);
+ verifyType(addrType, STRUCTTYPE_ADDRESS, StructType.class);
+
+ IDataType privTrait = cacheProvider.get(TRAITTYPE_PRIVILEGED);
+ verifyType(privTrait, TRAITTYPE_PRIVILEGED, TraitType.class);
+
+ IDataType shippingEnum = cacheProvider.get(ENUMTYPE_SHIPPING);
+ verifyType(shippingEnum, ENUMTYPE_SHIPPING, EnumType.class);
+ }
+
+ @Test
+ public void testCacheRemove() throws Exception {
+
+ cacheProvider.remove(CLASSTYPE_CUSTOMER);
+ assertNull(cacheProvider.get(CLASSTYPE_CUSTOMER));
+ assertFalse(cacheProvider.has(CLASSTYPE_CUSTOMER));
+ assertTrue(cacheProvider.getTypeNames(TypeCategory.CLASS).isEmpty());
+
+ final int EXPECTED_TYPE_COUNT = 3;
+ assertEquals(cacheProvider.getAllTypeNames().size(), EXPECTED_TYPE_COUNT);
+ }
+
+ @Test
+ public void testCacheRemoveByCategory() throws Exception {
+
+ cacheProvider.remove(TypeCategory.CLASS, CLASSTYPE_CUSTOMER);
+ assertNull(cacheProvider.get(CLASSTYPE_CUSTOMER));
+ assertFalse(cacheProvider.has(CLASSTYPE_CUSTOMER));
+ assertTrue(cacheProvider.getTypeNames(TypeCategory.CLASS).isEmpty());
+
+ final int EXPECTED_TYPE_COUNT = 3;
+ assertEquals(cacheProvider.getAllTypeNames().size(), EXPECTED_TYPE_COUNT);
+ }
+
+ @Test
+ public void testCacheClear() throws Exception {
+
+ cacheProvider.clear();
+
+ assertNull(cacheProvider.get(CLASSTYPE_CUSTOMER));
+ assertFalse(cacheProvider.has(CLASSTYPE_CUSTOMER));
+
+ assertNull(cacheProvider.get(STRUCTTYPE_ADDRESS));
+ assertFalse(cacheProvider.has(STRUCTTYPE_ADDRESS));
+
+ assertNull(cacheProvider.get(TRAITTYPE_PRIVILEGED));
+ assertFalse(cacheProvider.has(TRAITTYPE_PRIVILEGED));
+
+ assertNull(cacheProvider.get(ENUMTYPE_SHIPPING));
+ assertFalse(cacheProvider.has(ENUMTYPE_SHIPPING));
+
+ assertTrue(cacheProvider.getTypeNames(TypeCategory.CLASS).isEmpty());
+ assertTrue(cacheProvider.getTypeNames(TypeCategory.STRUCT).isEmpty());
+ assertTrue(cacheProvider.getTypeNames(TypeCategory.TRAIT).isEmpty());
+ assertTrue(cacheProvider.getTypeNames(TypeCategory.ENUM).isEmpty());
+
+ assertTrue(cacheProvider.getAllTypeNames().isEmpty());
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testPutTypeWithNullType() throws Exception {
+
+ cacheProvider.put(null);
+ fail("Null type should be not allowed in 'put'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testPutTypeWithInvalidType() throws Exception {
+
+ cacheProvider.put(DataTypes.BOOLEAN_TYPE);
+ fail("type should only be an instance of ClassType | EnumType | StructType | TraitType in 'put'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testGetTypeWithNullCategory() throws Exception {
+
+ cacheProvider.get(null, CLASSTYPE_CUSTOMER);
+ fail("Null TypeCategory should be not allowed in 'get'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testGetTypeWithInvalidCategory() throws Exception {
+
+ cacheProvider.get(TypeCategory.PRIMITIVE, DataTypes.BOOLEAN_TYPE.getName());
+ fail("TypeCategory should only be one of TypeCategory.CLASS | ENUM | STRUCT | TRAIT in 'get'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheHasTypeWithNullCategory() throws Exception {
+
+ cacheProvider.has(null, CLASSTYPE_CUSTOMER);
+ fail("Null TypeCategory should be not allowed in 'has'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheHasTypeWithInvalidCategory() throws Exception {
+
+ cacheProvider.has(TypeCategory.PRIMITIVE, DataTypes.BOOLEAN_TYPE.getName());
+ fail("TypeCategory should only be one of TypeCategory.CLASS | ENUM | STRUCT | TRAIT in 'has'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheGetTypeNamesByNullCategory() throws Exception {
+
+ cacheProvider.getTypeNames(null);
+ fail("Null TypeCategory should be not allowed in 'getNames'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheGetTypeNamesByInvalidCategory() throws Exception {
+
+ cacheProvider.getTypeNames(TypeCategory.PRIMITIVE);
+ fail("TypeCategory should only be one of TypeCategory.CLASS | ENUM | STRUCT | TRAIT in 'getNames'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheBulkInsertWithNullType() throws Exception {
+
+ List<IDataType> allTypes = new ArrayList<>();
+ allTypes.add(null);
+
+ // create a new cache provider instead of using the one setup for every method call
+ cacheProvider = new DefaultTypeCacheProvider();
+ cacheProvider.putAll(allTypes);
+
+ fail("Null type should be not allowed in 'putAll'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheBulkInsertWithInvalidType() throws Exception {
+
+ List<IDataType> allTypes = new ArrayList<>();
+ allTypes.add(DataTypes.BOOLEAN_TYPE);
+
+ // create a new cache provider instead of using the one setup for every method call
+ cacheProvider = new DefaultTypeCacheProvider();
+ cacheProvider.putAll(allTypes);
+
+ fail("type should only one of ClassType | EnumType | StructType | TraitType in 'putAll'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheRemoveByNullCategory() throws Exception {
+
+ cacheProvider.remove(null, CLASSTYPE_CUSTOMER);
+ fail("Null type should be not allowed in 'remove'");
+ }
+
+ @Test(expectedExceptions = AtlasException.class)
+ public void testCacheRemoveByInvalidCategory() throws Exception {
+
+ cacheProvider.remove(TypeCategory.PRIMITIVE, DataTypes.BOOLEAN_TYPE.getName());
+ fail("TypeCategory should only be one of TypeCategory.CLASS | ENUM | STRUCT | TRAIT in 'remove'");
+ }
+}