blob: 0d8647424372da4d9ba9aa4cbc606e749a92f642 [file] [log] [blame]
/**
* 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 org.apache.atlas.AtlasException;
import org.apache.atlas.annotation.ConditionalOnAtlasProperty;
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.HierarchicalType;
import org.apache.atlas.typesystem.types.IDataType;
import org.apache.atlas.typesystem.types.StructType;
import org.apache.atlas.typesystem.types.TraitType;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
/**
* Caches the types in-memory within the same process space.
*/
@SuppressWarnings("rawtypes")
@Singleton
@Component
@ConditionalOnAtlasProperty(property = "atlas.TypeCache.impl", isDefault = true)
public class DefaultTypeCache implements TypeCache {
private static final Logger LOG = LoggerFactory.getLogger(DefaultTypeCache.class);
private Map<String, IDataType> types_ = new ConcurrentHashMap<>();
private static final List<TypeCategory> validTypeFilterCategories =
Arrays.asList(TypeCategory.CLASS, TypeCategory.TRAIT, TypeCategory.ENUM, TypeCategory.STRUCT);
private static final List<TypeCategory> validSupertypeFilterCategories =
Arrays.asList(TypeCategory.CLASS, TypeCategory.TRAIT);
/*
* (non-Javadoc)
* @see
* org.apache.atlas.typesystem.types.cache.TypeCache#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.TypeCache#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(String typeCategory) {
assertValidTypeCategory(TypeCategory.valueOf(typeCategory));
}
private void assertValidTypeCategory(TypeCategory typeCategory) {
// 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 IllegalArgumentException("Category of the types to be filtered is null.");
}
if (!validTypeFilterCategories.contains(typeCategory)) {
throw new IllegalArgumentException("Category of the types should be one of " +
StringUtils.join(validTypeFilterCategories, ", "));
}
}
/*
* (non-Javadoc)
* @see
* org.apache.atlas.typesystem.types.cache.TypeCache#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.TypeCache#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);
}
/**
* Return the list of type names in the type system which match the specified filter.
*
* @return list of type names
* @param filterMap - Map of filter for type names. Valid keys are CATEGORY, SUPERTYPE, NOT_SUPERTYPE
* For example, CATEGORY = TRAIT && SUPERTYPE contains 'X' && SUPERTYPE !contains 'Y'
*/
@Override
public Collection<String> getTypeNames(Map<TYPE_FILTER, String> filterMap) throws AtlasException {
assertFilter(filterMap);
List<String> typeNames = new ArrayList<>();
for (IDataType type : types_.values()) {
if (shouldIncludeType(type, filterMap)) {
typeNames.add(type.getName());
}
}
return typeNames;
}
private boolean shouldIncludeType(IDataType type, Map<TYPE_FILTER, String> filterMap) {
if (filterMap == null) {
return true;
}
for (Entry<TYPE_FILTER, String> filterEntry : filterMap.entrySet()) {
switch (filterEntry.getKey()) {
case CATEGORY:
if (!filterEntry.getValue().equals(type.getTypeCategory().name())) {
return false;
}
break;
case SUPERTYPE:
if (!validSupertypeFilterCategories.contains(type.getTypeCategory()) ||
!((HierarchicalType) type).getAllSuperTypeNames().contains(filterEntry.getValue())) {
return false;
}
break;
case NOT_SUPERTYPE:
if (!validSupertypeFilterCategories.contains(type.getTypeCategory()) ||
type.getName().equals(filterEntry.getValue()) ||
((HierarchicalType) type).getAllSuperTypeNames().contains(filterEntry.getValue())) {
return false;
}
break;
}
}
return true;
}
private void assertFilter(Map<TYPE_FILTER, String> filterMap) throws AtlasException {
if (filterMap == null) {
return;
}
for (Entry<TYPE_FILTER, String> filterEntry : filterMap.entrySet()) {
switch (filterEntry.getKey()) {
case CATEGORY:
assertValidTypeCategory(filterEntry.getValue());
break;
case SUPERTYPE:
case NOT_SUPERTYPE:
if (!has(filterEntry.getValue())) {
if (LOG.isDebugEnabled()) {
LOG.debug("{}: supertype does not exist", filterEntry.getValue());
}
}
break;
default:
throw new IllegalStateException("Unhandled filter " + filterEntry.getKey());
}
}
}
/*
* (non-Javadoc)
* @see
* org.apache.atlas.typesystem.types.cache.TypeCache#getAllNames()
*/
@Override
public Collection<String> getAllTypeNames() throws AtlasException {
return types_.keySet();
}
/*
* (non-Javadoc)
* @see
* org.apache.atlas.typesystem.types.cache.TypeCache#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.TypeCache#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.TypeCache#remove(java
* .lang.String)
*/
@Override
public void remove(String typeName) throws AtlasException {
types_.remove(typeName);
}
/* (non-Javadoc)
* @see org.apache.atlas.typesystem.types.cache.TypeCache#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.TypeCache#clear()
*/
@Override
public void clear() {
types_.clear();
}
@Override
public IDataType onTypeFault(String typeName) throws AtlasException {
return null;
}
}