You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by yh...@apache.org on 2016/05/18 13:04:01 UTC
[5/5] incubator-atlas git commit: ATLAS-491 Business Catalog /
Taxonomy (jspeidel via yhemanth)
ATLAS-491 Business Catalog / Taxonomy (jspeidel via yhemanth)
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/aaf2971a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/aaf2971a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/aaf2971a
Branch: refs/heads/master
Commit: aaf2971ad16ccd9c37040f593121695cd8c9cacb
Parents: b65dd91
Author: Hemanth Yamijala <hy...@hortonworks.com>
Authored: Wed May 18 18:33:39 2016 +0530
Committer: Hemanth Yamijala <hy...@hortonworks.com>
Committed: Wed May 18 18:33:39 2016 +0530
----------------------------------------------------------------------
catalog/pom.xml | 122 +++++
.../apache/atlas/catalog/AtlasTypeSystem.java | 79 ++++
.../org/apache/atlas/catalog/BaseRequest.java | 62 +++
.../atlas/catalog/BaseResourceProvider.java | 40 ++
.../apache/atlas/catalog/CollectionRequest.java | 35 ++
.../atlas/catalog/DefaultDateFormatter.java | 39 ++
.../atlas/catalog/DefaultPropertyMapper.java | 142 ++++++
.../apache/atlas/catalog/DefaultTypeSystem.java | 130 ++++++
.../atlas/catalog/EntityResourceProvider.java | 72 +++
.../catalog/EntityTagResourceProvider.java | 135 ++++++
.../apache/atlas/catalog/InstanceRequest.java | 35 ++
.../apache/atlas/catalog/JsonSerializer.java | 90 ++++
.../apache/atlas/catalog/PropertyMapper.java | 45 ++
.../atlas/catalog/PropertyValueFormatter.java | 33 ++
.../java/org/apache/atlas/catalog/Request.java | 77 ++++
.../atlas/catalog/ResourceComparator.java | 62 +++
.../apache/atlas/catalog/ResourceProvider.java | 75 ++++
.../java/org/apache/atlas/catalog/Result.java | 50 +++
.../atlas/catalog/TaxonomyResourceProvider.java | 80 ++++
.../java/org/apache/atlas/catalog/TermPath.java | 111 +++++
.../atlas/catalog/TermResourceProvider.java | 128 ++++++
.../apache/atlas/catalog/TermVertexWrapper.java | 36 ++
.../org/apache/atlas/catalog/VertexWrapper.java | 111 +++++
.../definition/BaseResourceDefinition.java | 150 +++++++
.../definition/EntityResourceDefinition.java | 120 +++++
.../definition/EntityTagResourceDefinition.java | 105 +++++
.../catalog/definition/ResourceDefinition.java | 112 +++++
.../definition/TaxonomyResourceDefinition.java | 89 ++++
.../definition/TermResourceDefinition.java | 158 +++++++
.../catalog/exception/CatalogException.java | 36 ++
.../exception/CatalogRuntimeException.java | 43 ++
.../exception/InvalidPayloadException.java | 39 ++
.../exception/InvalidQueryException.java | 28 ++
.../ResourceAlreadyExistsException.java | 28 ++
.../exception/ResourceNotFoundException.java | 28 ++
.../catalog/projection/GenericRelation.java | 80 ++++
.../atlas/catalog/projection/Projection.java | 66 +++
.../catalog/projection/ProjectionResult.java | 51 +++
.../atlas/catalog/projection/Relation.java | 53 +++
.../catalog/projection/RelationProjection.java | 69 +++
.../atlas/catalog/projection/RelationSet.java | 45 ++
.../atlas/catalog/projection/TagRelation.java | 73 +++
.../atlas/catalog/projection/TraitRelation.java | 76 ++++
.../catalog/query/AlwaysQueryExpression.java | 46 ++
.../atlas/catalog/query/AtlasEntityQuery.java | 40 ++
.../catalog/query/AtlasEntityTagQuery.java | 73 +++
.../apache/atlas/catalog/query/AtlasQuery.java | 37 ++
.../atlas/catalog/query/AtlasTaxonomyQuery.java | 37 ++
.../atlas/catalog/query/AtlasTermQuery.java | 44 ++
.../apache/atlas/catalog/query/BaseQuery.java | 121 +++++
.../catalog/query/BaseQueryExpression.java | 105 +++++
.../catalog/query/BooleanQueryExpression.java | 141 ++++++
.../catalog/query/PrefixQueryExpression.java | 39 ++
.../query/ProjectionQueryExpression.java | 122 +++++
.../atlas/catalog/query/QueryExpression.java | 99 +++++
.../atlas/catalog/query/QueryFactory.java | 182 ++++++++
.../catalog/query/RegexQueryExpression.java | 41 ++
.../catalog/query/TermQueryExpression.java | 52 +++
.../catalog/query/TermRangeQueryExpression.java | 61 +++
.../catalog/query/WildcardQueryExpression.java | 43 ++
.../atlas/catalog/CollectionRequestTest.java | 74 ++++
.../atlas/catalog/DefaultDateFormatterTest.java | 41 ++
.../catalog/DefaultPropertyMapperTest.java | 177 ++++++++
.../catalog/EntityResourceProviderTest.java | 215 +++++++++
.../catalog/EntityTagResourceProviderTest.java | 444 +++++++++++++++++++
.../atlas/catalog/InstanceRequestTest.java | 67 +++
.../atlas/catalog/JsonSerializerTest.java | 120 +++++
.../atlas/catalog/ResourceComparatorTest.java | 61 +++
.../catalog/TaxonomyResourceProviderTest.java | 287 ++++++++++++
.../atlas/catalog/TermResourceProviderTest.java | 355 +++++++++++++++
.../apache/atlas/catalog/VertexWrapperTest.java | 311 +++++++++++++
.../EntityResourceDefinitionTest.java | 140 ++++++
.../EntityTagResourceDefinitionTest.java | 177 ++++++++
.../TaxonomyResourceDefinitionTest.java | 174 ++++++++
.../definition/TermResourceDefinitionTest.java | 210 +++++++++
.../query/AlwaysQueryExpressionTest.java | 74 ++++
.../atlas/catalog/query/QueryFactoryTest.java | 209 +++++++++
distro/src/conf/policy-store.txt | 10 +-
pom.xml | 9 +-
release-log.txt | 1 +
.../atlas/services/DefaultMetadataService.java | 50 ++-
.../apache/atlas/services/MetadataService.java | 28 ++
webapp/pom.xml | 5 +
.../authorize/AtlasAuthorizationUtils.java | 25 +-
.../atlas/authorize/AtlasResourceTypes.java | 2 +-
.../apache/atlas/web/resources/BaseService.java | 126 ++++++
.../web/resources/CatalogExceptionMapper.java | 62 +++
.../CatalogRuntimeExceptionMapper.java | 78 ++++
.../atlas/web/resources/EntityService.java | 147 ++++++
.../atlas/web/resources/TaxonomyService.java | 201 +++++++++
webapp/src/main/webapp/WEB-INF/web.xml | 5 +
.../authorize/AtlasAuthorizationUtilsTest.java | 121 +++++
92 files changed, 8500 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/pom.xml
----------------------------------------------------------------------
diff --git a/catalog/pom.xml b/catalog/pom.xml
new file mode 100755
index 0000000..8a49d3d
--- /dev/null
+++ b/catalog/pom.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ 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.
+ -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.atlas</groupId>
+ <artifactId>apache-atlas</artifactId>
+ <version>0.7-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>atlas-catalog</artifactId>
+ <description>Apache Atlas Business Catalog Module</description>
+ <name>Apache Atlas Business Catalog</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.atlas</groupId>
+ <artifactId>atlas-repository</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.atlas</groupId>
+ <artifactId>atlas-typesystem</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.atlas</groupId>
+ <artifactId>atlas-server-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-throwingproviders</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-multibindings</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.tinkerpop.blueprints</groupId>
+ <artifactId>blueprints-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.tinkerpop.gremlin</groupId>
+ <artifactId>gremlin-java</artifactId>
+ </dependency>
+
+ <!-- testing -->
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.4</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <excludes>
+ <exclude>**/log4j.xml</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/AtlasTypeSystem.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/AtlasTypeSystem.java b/catalog/src/main/java/org/apache/atlas/catalog/AtlasTypeSystem.java
new file mode 100644
index 0000000..6f2e0be
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/AtlasTypeSystem.java
@@ -0,0 +1,79 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.exception.ResourceAlreadyExistsException;
+
+import java.util.Map;
+
+/**
+ * Abstraction for Atlas Type System.
+ */
+public interface AtlasTypeSystem {
+
+ /**
+ * Create a Type in the Atlas Type System if it doesn't already exist.
+ * If the type already exists, this method has no affect.
+ *
+ * @param resourceDefinition resource definition for type being created
+ * @param name type name
+ * @param description description of the type being created
+ *
+ * @throws ResourceAlreadyExistsException if entity already exists
+ */
+ void createClassType(ResourceDefinition resourceDefinition, String name, String description)
+ throws ResourceAlreadyExistsException;
+
+ /**
+ * Create an entity in the Atlas Type System for the provided request and resource definition.
+ * If Type associated with the entity doesn't already exist, it is created.
+ *
+ * @param definition the definition of the resource for which we are creating the entity
+ * @param request the user request
+ *
+ * @throws ResourceAlreadyExistsException if type already exists
+ */
+ void createEntity(ResourceDefinition definition, Request request)
+ throws ResourceAlreadyExistsException;
+
+ /**
+ * Create a trait instance instance in the Atlas Type System.
+ *
+ * @param resourceDefinition resource definition for trait type being created
+ * @param name type name
+ * @param description description of the type being created
+ *
+ * @throws ResourceAlreadyExistsException if type already exists
+ */
+ void createTraitType(ResourceDefinition resourceDefinition, String name, String description)
+ throws ResourceAlreadyExistsException;
+
+ /**
+ * Create a trait instance in the Atlas Type System and associate it with the entity identified by the provided guid.
+ *
+ * @param guid id of the entity which will be associated with the trait instance
+ * @param typeName type name of the trait
+ * @param properties property map used to populate the trait instance
+ *
+ * @throws ResourceAlreadyExistsException if trait instance is already associated with the entity
+ */
+ void createTraitInstance(String guid, String typeName, Map<String, Object> properties)
+ throws ResourceAlreadyExistsException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/BaseRequest.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/BaseRequest.java b/catalog/src/main/java/org/apache/atlas/catalog/BaseRequest.java
new file mode 100644
index 0000000..f3376b0
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/BaseRequest.java
@@ -0,0 +1,62 @@
+/**
+ * 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.catalog;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * Base user API request.
+ */
+public abstract class BaseRequest implements Request {
+ private final Map<String, Object> properties = new HashMap<>();
+ private final String queryString;
+ private final Collection<String> additionalSelectProperties = new HashSet<>();
+
+ protected BaseRequest(Map<String, Object> properties, String queryString) {
+ if (properties != null) {
+ this.properties.putAll((properties));
+ }
+ this.queryString = queryString;
+ }
+
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ public <T> T getProperty(String name) {
+ return (T)properties.get(name);
+ }
+
+ public String getQueryString() {
+ return queryString;
+ }
+
+ @Override
+ public void addAdditionalSelectProperties(Collection<String> resultProperties) {
+ additionalSelectProperties.addAll(resultProperties);
+ }
+
+ @Override
+ public Collection<String> getAdditionalSelectProperties() {
+ return additionalSelectProperties;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/BaseResourceProvider.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/BaseResourceProvider.java b/catalog/src/main/java/org/apache/atlas/catalog/BaseResourceProvider.java
new file mode 100644
index 0000000..517eaf6
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/BaseResourceProvider.java
@@ -0,0 +1,40 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.query.QueryFactory;
+
+import java.util.*;
+
+/**
+ * Base class for resource providers.
+ */
+public abstract class BaseResourceProvider implements ResourceProvider {
+ protected AtlasTypeSystem typeSystem;
+ protected QueryFactory queryFactory = new QueryFactory();
+
+ protected BaseResourceProvider(AtlasTypeSystem typeSystem) {
+ this.typeSystem = typeSystem;
+ }
+
+ protected void setQueryFactory(QueryFactory factory) {
+ queryFactory = factory;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/CollectionRequest.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/CollectionRequest.java b/catalog/src/main/java/org/apache/atlas/catalog/CollectionRequest.java
new file mode 100644
index 0000000..b1be1ae
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/CollectionRequest.java
@@ -0,0 +1,35 @@
+/**
+ * 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.catalog;
+
+import java.util.Map;
+
+/**
+ * A request for a collection resource.
+ */
+public class CollectionRequest extends BaseRequest {
+ public CollectionRequest(Map<String, Object> properties, String queryString) {
+ super(properties, queryString);
+ }
+
+ @Override
+ public Cardinality getCardinality() {
+ return Cardinality.COLLECTION;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/DefaultDateFormatter.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/DefaultDateFormatter.java b/catalog/src/main/java/org/apache/atlas/catalog/DefaultDateFormatter.java
new file mode 100644
index 0000000..df07505
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/DefaultDateFormatter.java
@@ -0,0 +1,39 @@
+/**
+ * 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.catalog;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+/**
+ * Format a date field which is represented as a long.
+ */
+public class DefaultDateFormatter implements PropertyValueFormatter<Long, String> {
+
+ //todo: obtain format from atlas proper
+ public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss");
+
+ @Override
+ public String format(Long l) {
+ Calendar calendar = new GregorianCalendar();
+ calendar.setTimeInMillis(l);
+ return DATE_FORMAT.format(calendar.getTime());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/DefaultPropertyMapper.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/DefaultPropertyMapper.java b/catalog/src/main/java/org/apache/atlas/catalog/DefaultPropertyMapper.java
new file mode 100644
index 0000000..2f52b3b
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/DefaultPropertyMapper.java
@@ -0,0 +1,142 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.catalog.exception.CatalogRuntimeException;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.typesystem.types.FieldMapping;
+import org.apache.atlas.typesystem.types.HierarchicalType;
+import org.apache.atlas.typesystem.types.TypeSystem;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Default property mapper which translates property names to/from name exposed in API to internal fully qualified name.
+ */
+public class DefaultPropertyMapper implements PropertyMapper {
+ //todo: abstract HierarchicalType
+ private Map<String, HierarchicalType> typeInstances = new HashMap<>();
+ private final Map<String, String> m_qualifiedToCleanMap = new HashMap<>();
+ private final Map<String, String> m_cleanToQualifiedMap = new HashMap<>();
+
+
+ public DefaultPropertyMapper() {
+ this(Collections.<String, String>emptyMap(), Collections.<String, String>emptyMap());
+ }
+
+ public DefaultPropertyMapper(Map<String, String> qualifiedToCleanMap,
+ Map<String, String> cleanToQualifiedMap) {
+ setDefaultMappings();
+
+ m_qualifiedToCleanMap.putAll(qualifiedToCleanMap);
+ m_cleanToQualifiedMap.putAll(cleanToQualifiedMap);
+ }
+
+ @Override
+ public String toCleanName(String propName, String type) {
+ HierarchicalType dataType = getDataType(type);
+ String replacement = m_qualifiedToCleanMap.get(propName);
+ if (replacement == null && dataType != null) {
+ FieldMapping fieldMap = dataType.fieldMapping();
+ if (! fieldMap.fields.containsKey(propName) && propName.contains(".")) {
+ String cleanName = propName.substring(propName.lastIndexOf('.') + 1);
+ if (fieldMap.fields.containsKey(cleanName)) {
+ replacement = cleanName;
+ }
+ }
+ }
+
+ if (replacement == null) {
+ replacement = propName;
+ }
+ return replacement;
+ }
+
+ @Override
+ public String toFullyQualifiedName(String propName, String type) {
+ HierarchicalType dataType = getDataType(type);
+ String replacement = m_cleanToQualifiedMap.get(propName);
+ if (replacement == null && dataType != null) {
+ FieldMapping fieldMap = dataType.fieldMapping();
+ if (fieldMap.fields.containsKey(propName)) {
+ try {
+ replacement = dataType.getQualifiedName(propName);
+ } catch (AtlasException e) {
+ throw new CatalogRuntimeException(String.format(
+ "Unable to resolve fully qualified property name for type '%s': %s", type, e), e);
+ }
+ }
+ }
+
+ if (replacement == null) {
+ replacement = propName;
+ }
+ return replacement;
+ }
+
+ //todo: abstract this via AtlasTypeSystem
+ protected synchronized HierarchicalType getDataType(String type) {
+ HierarchicalType dataType = typeInstances.get(type);
+ //todo: are there still cases where type can be null?
+ if (dataType == null) {
+ dataType = createDataType(type);
+ typeInstances.put(type, dataType);
+ }
+ return dataType;
+ }
+
+ protected HierarchicalType createDataType(String type) {
+ try {
+ return TypeSystem.getInstance().getDataType(HierarchicalType.class, type);
+ } catch (AtlasException e) {
+ throw new CatalogRuntimeException("Unable to get type instance from type system for type: " + type, e);
+ }
+ }
+
+ private void setDefaultMappings() {
+ //todo: these are all internal "__*" properties
+ //todo: should be able to ask type system for the "clean" name for these
+ m_qualifiedToCleanMap.put(Constants.GUID_PROPERTY_KEY, "id");
+ m_cleanToQualifiedMap.put("id", Constants.GUID_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.TIMESTAMP_PROPERTY_KEY, "creation_time");
+ m_cleanToQualifiedMap.put("creation_time", Constants.TIMESTAMP_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, "modified_time");
+ m_cleanToQualifiedMap.put("modified_time", Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.ENTITY_TYPE_PROPERTY_KEY, "type");
+ m_cleanToQualifiedMap.put("type", Constants.ENTITY_TYPE_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.VERSION_PROPERTY_KEY, "version");
+ m_cleanToQualifiedMap.put("version", Constants.VERSION_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait_names");
+ m_cleanToQualifiedMap.put("trait_names", Constants.TRAIT_NAMES_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.SUPER_TYPES_PROPERTY_KEY, "super_types");
+ m_cleanToQualifiedMap.put("super_types", Constants.SUPER_TYPES_PROPERTY_KEY);
+
+ m_qualifiedToCleanMap.put(Constants.STATE_PROPERTY_KEY, "state");
+ m_cleanToQualifiedMap.put("state", Constants.STATE_PROPERTY_KEY);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/DefaultTypeSystem.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/DefaultTypeSystem.java b/catalog/src/main/java/org/apache/atlas/catalog/DefaultTypeSystem.java
new file mode 100644
index 0000000..f71c061
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/DefaultTypeSystem.java
@@ -0,0 +1,130 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.exception.CatalogRuntimeException;
+import org.apache.atlas.catalog.exception.ResourceAlreadyExistsException;
+import org.apache.atlas.services.MetadataService;
+import org.apache.atlas.typesystem.ITypedReferenceableInstance;
+import org.apache.atlas.typesystem.Referenceable;
+import org.apache.atlas.typesystem.Struct;
+import org.apache.atlas.typesystem.exception.EntityExistsException;
+import org.apache.atlas.typesystem.exception.TypeExistsException;
+import org.apache.atlas.typesystem.json.TypesSerialization;
+import org.apache.atlas.typesystem.types.*;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Default implementation.
+ */
+public class DefaultTypeSystem implements AtlasTypeSystem {
+ private final MetadataService metadataService;
+
+ /**
+ * Constructor.
+ *
+ * @param metadataService atlas metadata service
+ */
+ public DefaultTypeSystem(MetadataService metadataService) {
+ this.metadataService = metadataService;
+ }
+
+ @Override
+ public void createEntity(ResourceDefinition definition, Request request) throws ResourceAlreadyExistsException {
+ String typeName = definition.getTypeName();
+ try {
+ createClassType(definition, typeName, typeName + " Definition");
+ } catch (ResourceAlreadyExistsException e) {
+ // ok if type already exists
+ }
+ try {
+ Referenceable entity = new Referenceable(typeName, request.getProperties());
+ ITypedReferenceableInstance typedInstance = metadataService.getTypedReferenceableInstance(entity);
+ metadataService.createEntities(Collections.singletonList(typedInstance).toArray(new ITypedReferenceableInstance[1]));
+ } catch (EntityExistsException e) {
+ throw new ResourceAlreadyExistsException(
+ "Attempted to create an entity which already exists: " + request.getProperties());
+ } catch (AtlasException e) {
+ throw new CatalogRuntimeException("An expected exception occurred creating an entity: " + e, e);
+ }
+ }
+
+ @Override
+ public void createClassType(ResourceDefinition resourceDefinition, String name, String description)
+ throws ResourceAlreadyExistsException {
+
+ createType(resourceDefinition.getPropertyDefinitions(), ClassType.class, name, description, false);
+ }
+
+ @Override
+ public void createTraitType(ResourceDefinition resourceDefinition, String name, String description)
+ throws ResourceAlreadyExistsException {
+
+ createType(resourceDefinition.getPropertyDefinitions(), TraitType.class, name, description, true);
+ }
+
+ public void createTraitInstance(String guid, String typeName, Map<String, Object> properties)
+ throws ResourceAlreadyExistsException {
+
+ try {
+ // not using the constructor with properties argument because it is marked 'InterfaceAudience.Private'
+ Struct struct = new Struct(typeName);
+ for (Map.Entry<String, Object> propEntry : properties.entrySet()) {
+ struct.set(propEntry.getKey(), propEntry.getValue());
+ }
+ metadataService.addTrait(guid, metadataService.createTraitInstance(struct));
+ } catch (IllegalArgumentException e) {
+ //todo: unfortunately, IllegalArgumentException can be thrown for other reasons
+ if (e.getMessage().contains("is already defined for entity")) {
+ throw new ResourceAlreadyExistsException(
+ String.format("Tag '%s' already associated with the entity", typeName));
+ } else {
+ throw e;
+ }
+ } catch (AtlasException e) {
+ throw new CatalogRuntimeException(String.format(
+ "Unable to create trait instance '%s' in type system: %s", typeName, e), e);
+ }
+ }
+
+ private <T extends HierarchicalType> void createType(Collection<AttributeDefinition> attributes,
+ Class<T> type,
+ String name,
+ String description,
+ boolean isTrait)
+ throws ResourceAlreadyExistsException {
+
+ try {
+ HierarchicalTypeDefinition<T> definition = new HierarchicalTypeDefinition<>(type, name, description, null,
+ attributes.toArray(new AttributeDefinition[attributes.size()]));
+
+ metadataService.createType(TypesSerialization.toJson(definition, isTrait));
+ } catch (TypeExistsException e) {
+ throw new ResourceAlreadyExistsException(String.format("Type '%s' already exists", name));
+ } catch (AtlasException e) {
+ throw new CatalogRuntimeException(String.format(
+ "Unable to create type '%s' in type system: %s", name, e), e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/EntityResourceProvider.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/EntityResourceProvider.java b/catalog/src/main/java/org/apache/atlas/catalog/EntityResourceProvider.java
new file mode 100644
index 0000000..c8d6f68
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/EntityResourceProvider.java
@@ -0,0 +1,72 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.definition.EntityResourceDefinition;
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.exception.*;
+import org.apache.atlas.catalog.query.AtlasQuery;
+
+import java.util.*;
+
+/**
+ * Provider for entity resources.
+ */
+public class EntityResourceProvider extends BaseResourceProvider implements ResourceProvider {
+ private final static ResourceDefinition resourceDefinition = new EntityResourceDefinition();
+
+ public EntityResourceProvider(AtlasTypeSystem typeSystem) {
+ super(typeSystem);
+ }
+
+ @Override
+ public Result getResourceById(Request request) throws ResourceNotFoundException {
+ AtlasQuery atlasQuery;
+ try {
+ atlasQuery = queryFactory.createEntityQuery(request);
+ } catch (InvalidQueryException e) {
+ throw new CatalogRuntimeException("Unable to compile internal Entity query: " + e, e);
+ }
+ Collection<Map<String, Object>> results = atlasQuery.execute();
+ if (results.isEmpty()) {
+ throw new ResourceNotFoundException(String.format("Entity '%s' not found.",
+ request.getProperty(resourceDefinition.getIdPropertyName())));
+ }
+ return new Result(results);
+ }
+
+ @Override
+ public Result getResources(Request request) throws InvalidQueryException, ResourceNotFoundException {
+ AtlasQuery atlasQuery = queryFactory.createEntityQuery(request);
+ return new Result(atlasQuery.execute());
+ }
+
+ @Override
+ public void createResource(Request request)
+ throws InvalidPayloadException, ResourceAlreadyExistsException, ResourceNotFoundException {
+
+ // creation of entities is currently unsupported
+ throw new UnsupportedOperationException("Creation of entities is not currently supported");
+ }
+
+ @Override
+ public Collection<String> createResources(Request request) throws InvalidQueryException, ResourceNotFoundException {
+ throw new UnsupportedOperationException("Creation of entities is not currently supported");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/EntityTagResourceProvider.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/EntityTagResourceProvider.java b/catalog/src/main/java/org/apache/atlas/catalog/EntityTagResourceProvider.java
new file mode 100644
index 0000000..dc4ab0d
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/EntityTagResourceProvider.java
@@ -0,0 +1,135 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.definition.EntityTagResourceDefinition;
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.exception.*;
+import org.apache.atlas.catalog.query.AtlasQuery;
+
+import java.util.*;
+
+/**
+ * Provider for entity tag resources.
+ */
+public class EntityTagResourceProvider extends BaseResourceProvider implements ResourceProvider {
+ private final static ResourceDefinition resourceDefinition = new EntityTagResourceDefinition();
+ private TermResourceProvider termResourceProvider;
+
+ public EntityTagResourceProvider(AtlasTypeSystem typeSystem) {
+ super(typeSystem);
+
+ }
+
+ @Override
+ public Result getResourceById(Request request) throws ResourceNotFoundException {
+ AtlasQuery atlasQuery;
+ try {
+ atlasQuery = queryFactory.createEntityTagQuery(request);
+ } catch (InvalidQueryException e) {
+ throw new CatalogRuntimeException("Unable to compile internal Entity Tag query: " + e, e);
+ }
+ Collection<Map<String, Object>> results = atlasQuery.execute();
+ if (results.isEmpty()) {
+ throw new ResourceNotFoundException(String.format("Tag '%s' not found.",
+ request.getProperty(resourceDefinition.getIdPropertyName())));
+ }
+
+ return new Result(results);
+ }
+
+ @Override
+ public Result getResources(Request request) throws InvalidQueryException, ResourceNotFoundException {
+ AtlasQuery atlasQuery = queryFactory.createEntityTagQuery(request);
+ return new Result(atlasQuery.execute());
+ }
+
+ @Override
+ public void createResource(Request request)
+ throws InvalidPayloadException, ResourceAlreadyExistsException, ResourceNotFoundException {
+
+ String entityId = String.valueOf(request.getProperties().remove("id"));
+ resourceDefinition.validate(request);
+ Result termResult = getTermQueryResult(request.<String>getProperty("name"));
+ Map<String, Object> termProperties = termResult.getPropertyMaps().iterator().next();
+ //todo: use constant for property name
+ if (String.valueOf(termProperties.get("available_as_tag")).equals("false")) {
+ throw new InvalidPayloadException(
+ "Attempted to tag an entity with a term which is not available to be tagged");
+ }
+ tagEntities(Collections.singleton(entityId), termProperties);
+ }
+
+ //todo: response for case mixed case where some subset of creations fail
+ @Override
+ public Collection<String> createResources(Request request)
+ throws InvalidQueryException, ResourceNotFoundException, ResourceAlreadyExistsException {
+
+ Collection<String> relativeUrls = new ArrayList<>();
+ AtlasQuery atlasQuery = queryFactory.createEntityQuery(request);
+ Collection<String> guids = new ArrayList<>();
+ for (Map<String, Object> entityMap: atlasQuery.execute()) {
+ guids.add(String.valueOf(entityMap.get("id")));
+ }
+
+ Collection<Map<String, String>> tagMaps = request.getProperty("tags");
+ for (Map<String, String> tagMap : tagMaps) {
+ Result termResult = getTermQueryResult(tagMap.get("name"));
+ relativeUrls.addAll(tagEntities(guids, termResult.getPropertyMaps().iterator().next()));
+ }
+ return relativeUrls;
+ }
+
+ private Result getTermQueryResult(String termName) throws ResourceNotFoundException {
+ Request tagRequest = new InstanceRequest(
+ Collections.<String, Object>singletonMap("termPath", new TermPath(termName)));
+
+ tagRequest.addAdditionalSelectProperties(Collections.singleton("type"));
+ return getTermResourceProvider().getResourceById(tagRequest);
+ }
+
+ private Collection<String> tagEntities(Collection<String> entityGuids, Map<String, Object> termProperties)
+ throws ResourceAlreadyExistsException {
+
+ Collection<String> relativeUrls = new ArrayList<>();
+ for (String guid : entityGuids) {
+ //createTermEdge(entity, Collections.singleton(termVertex));
+ // copy term properties from trait associated with taxonomy to be set
+ // on trait associated with new entity (basically clone at time of tag event)
+ //todo: any changes to 'singleton' trait won't be reflected in new trait
+ //todo: iterate over properties in term definition instead of hard coding here
+ Map<String, Object> properties = new HashMap<>();
+ String termName = String.valueOf(termProperties.get("name"));
+ properties.put("name", termName);
+ properties.put("description", termProperties.get("description"));
+
+ typeSystem.createTraitInstance(guid, termName, properties);
+ //todo: *** shouldn't know anything about href structure in this class ***
+ relativeUrls.add(String.format("v1/entities/%s/tags/%s", guid, termName));
+ }
+ return relativeUrls;
+ }
+
+ protected synchronized ResourceProvider getTermResourceProvider() {
+ if (termResourceProvider == null) {
+ termResourceProvider = new TermResourceProvider(typeSystem);
+ }
+ return termResourceProvider;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/InstanceRequest.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/InstanceRequest.java b/catalog/src/main/java/org/apache/atlas/catalog/InstanceRequest.java
new file mode 100644
index 0000000..01583c4
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/InstanceRequest.java
@@ -0,0 +1,35 @@
+/**
+ * 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.catalog;
+
+import java.util.Map;
+
+/**
+ * A request for an instance resource.
+ */
+public class InstanceRequest extends BaseRequest {
+ public InstanceRequest(Map<String, Object> properties) {
+ super(properties, null);
+ }
+
+ @Override
+ public Cardinality getCardinality() {
+ return Cardinality.INSTANCE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/JsonSerializer.java b/catalog/src/main/java/org/apache/atlas/catalog/JsonSerializer.java
new file mode 100644
index 0000000..a75639f
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/JsonSerializer.java
@@ -0,0 +1,90 @@
+/**
+ * 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.catalog;
+
+import com.google.gson.stream.JsonWriter;
+import org.apache.atlas.catalog.exception.CatalogRuntimeException;
+
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * JSON serializer.
+ */
+public class JsonSerializer {
+ public String serialize(Result result, UriInfo ui) {
+ Writer json = new StringWriter();
+ JsonWriter writer = new JsonWriter(json);
+ writer.setIndent(" ");
+
+ try {
+ writeValue(writer, result.getPropertyMaps(), ui.getBaseUri().toASCIIString());
+ } catch (IOException e) {
+ throw new CatalogRuntimeException("Unable to write JSON response.", e);
+ }
+ return json.toString();
+ }
+
+ private void writeValue(JsonWriter writer, Object value, String baseUrl) throws IOException {
+ if (value == null) {
+ writer.nullValue();
+ } else if (value instanceof Map) {
+ writer.beginObject();
+ LinkedHashMap<String, Object> nonScalarMap = new LinkedHashMap<>();
+ for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet()) {
+ String key = entry.getKey();
+ Object val = entry.getValue();
+
+ if (val == null || ! (val instanceof Collection || val instanceof Map)) {
+ //todo: use a token in value instead of prop name
+ if (key.equals("href")) {
+ val = baseUrl + String.valueOf(val);
+ }
+ writer.name(key);
+ writeValue(writer, val, baseUrl);
+ } else {
+ nonScalarMap.put(key, val);
+ }
+ }
+ for (Map.Entry<String, Object> entry : nonScalarMap.entrySet()) {
+ writer.name(entry.getKey());
+ writeValue(writer, entry.getValue(), baseUrl);
+ }
+ writer.endObject();
+ } else if (value instanceof Collection) {
+ writer.beginArray();
+ for (Object o : (Collection) value) {
+ writeValue(writer, o, baseUrl);
+ }
+ writer.endArray();
+ } else if (value instanceof Number) {
+ writer.value((Number) value);
+ } else if (value instanceof Boolean) {
+ writer.value((Boolean) value);
+ } else {
+ // everything else is String
+ writer.value(String.valueOf(value));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/PropertyMapper.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/PropertyMapper.java b/catalog/src/main/java/org/apache/atlas/catalog/PropertyMapper.java
new file mode 100644
index 0000000..50ee275
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/PropertyMapper.java
@@ -0,0 +1,45 @@
+/**
+ * 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.catalog;
+
+
+/**
+ * Translates property names to/from name exposed in API to internal fully qualified name.
+ */
+public interface PropertyMapper {
+ /**
+ * Translate a qualified name to a clean name.
+ *
+ * @param propName property name to translate
+ * @param type resource type
+ *
+ * @return clean property name
+ */
+ String toCleanName(String propName, String type);
+
+ /**
+ * Translate a clean name to a fully qualified name.
+ *
+ * @param propName property name to translate
+ * @param type resource type
+ *
+ * @return fully qualified property name
+ */
+ String toFullyQualifiedName(String propName, String type);
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/PropertyValueFormatter.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/PropertyValueFormatter.java b/catalog/src/main/java/org/apache/atlas/catalog/PropertyValueFormatter.java
new file mode 100644
index 0000000..a42f528
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/PropertyValueFormatter.java
@@ -0,0 +1,33 @@
+/**
+ * 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.catalog;
+
+/**
+ * A rule for translating a property value.
+ */
+public interface PropertyValueFormatter <T,V> {
+ /**
+ * Format a property value.
+ *
+ * @param value property value to format
+ *
+ * @return formatted property value
+ */
+ V format(T value);
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/Request.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/Request.java b/catalog/src/main/java/org/apache/atlas/catalog/Request.java
new file mode 100644
index 0000000..7dc781a
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/Request.java
@@ -0,0 +1,77 @@
+/**
+ * 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.catalog;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Represents a user request.
+ */
+public interface Request {
+ /**
+ * Request cardinality enum.
+ */
+ enum Cardinality {INSTANCE, COLLECTION}
+
+ /**
+ * Get request properties.
+ *
+ * @return request property map
+ */
+ Map<String, Object> getProperties();
+
+ /**
+ * Get the value of a specified property.
+ *
+ * @param name property name
+ * @param <T> value type
+ *
+ * @return value for the requested property or null if property not in map
+ */
+ <T> T getProperty(String name);
+
+ /**
+ * Get the query string.
+ *
+ * @return the user specified query string or null
+ */
+ String getQueryString();
+
+ /**
+ * Get the cardinality of the request.
+ *
+ * @return the request cardinality
+ */
+ Cardinality getCardinality();
+
+ /**
+ * Add additional property names which should be returned in the result.
+ *
+ * @param resultProperties collection of property names
+ */
+ void addAdditionalSelectProperties(Collection<String> resultProperties);
+
+ /**
+ * Get any additional property names which should be included in the result.
+ *
+ * @return collection of added property names or an empty collection
+ */
+ Collection<String> getAdditionalSelectProperties();
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/ResourceComparator.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/ResourceComparator.java b/catalog/src/main/java/org/apache/atlas/catalog/ResourceComparator.java
new file mode 100644
index 0000000..deb2e4c
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/ResourceComparator.java
@@ -0,0 +1,62 @@
+/**
+ * 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.catalog;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Provides key ordering for resource property maps.
+ * Ordering can be defined explicitly for specific properties,
+ * otherwise natural ordering is used.
+ */
+public class ResourceComparator implements Comparator<String> {
+ private static List<String> ordering = new ArrayList<>();
+
+ @Override
+ public int compare(String s1, String s2) {
+ if (s1.equals(s2)) {
+ return 0;
+ }
+
+ int s1Order = ordering.indexOf(s1);
+ int s2Order = ordering.indexOf(s2);
+
+ if (s1Order == -1 && s2Order == -1) {
+ return s1.compareTo(s2);
+ }
+
+ if (s1Order != -1 && s2Order != -1) {
+ return s1Order - s2Order;
+ }
+
+ return s1Order == -1 ? 1 : -1;
+
+ }
+
+ //todo: each resource definition can provide its own ordering list
+ static {
+ ordering.add("href");
+ ordering.add("name");
+ ordering.add("id");
+ ordering.add("description");
+ ordering.add("type");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/ResourceProvider.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/ResourceProvider.java b/catalog/src/main/java/org/apache/atlas/catalog/ResourceProvider.java
new file mode 100644
index 0000000..4c4319c
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/ResourceProvider.java
@@ -0,0 +1,75 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.exception.*;
+
+import java.util.Collection;
+
+/**
+ * Provider for a resource type.
+ */
+public interface ResourceProvider {
+ /**
+ * Get a resource by primary key.
+ *
+ * @param request request instance which contains the required id properties and no query string
+ * @return result containing the requested resource; never null
+ *
+ * @throws ResourceNotFoundException if the requested resource isn't found
+ */
+ Result getResourceById(Request request) throws ResourceNotFoundException;
+
+ /**
+ * Get all resources which match the provider query.
+ *
+ * @param request request instance which will include a query string and possibly properties
+ * @return result containing collection of matching resources. If no resources match
+ * a result is returned with no resources
+ *
+ * @throws InvalidQueryException if the user query contains invalid syntax
+ * @throws ResourceNotFoundException if a parent resource of the requested resource doesn't exist
+ */
+ Result getResources(Request request) throws InvalidQueryException, ResourceNotFoundException;
+
+ /**
+ * Create a single resource.
+ *
+ * @param request request instance containing the contents of the resource to create
+ *
+ * @throws InvalidPayloadException if the payload or any other part of the user request is invalid
+ * @throws ResourceAlreadyExistsException if the resource already exists
+ * @throws ResourceNotFoundException if a parent of the resource to create doesn't exist
+ */
+ void createResource(Request request)
+ throws InvalidPayloadException, ResourceAlreadyExistsException, ResourceNotFoundException;
+
+ //todo: define the behavior for partial success
+ /**
+ * Create multiple resources.
+ *
+ * @param request request instance containing the contents of 1..n resources
+ * @return collection of relative urls for the created resources
+ *
+ * @throws InvalidPayloadException if the payload or any other part of the user request is invalid
+ * @throws ResourceAlreadyExistsException if the resource already exists
+ * @throws ResourceNotFoundException if a parent of the resource to create doesn't exist
+ */
+ Collection<String> createResources(Request request) throws CatalogException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/Result.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/Result.java b/catalog/src/main/java/org/apache/atlas/catalog/Result.java
new file mode 100644
index 0000000..34a81ab
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/Result.java
@@ -0,0 +1,50 @@
+/**
+ * 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.catalog;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Resource provider result.
+ */
+public class Result {
+ /**
+ * collection of property maps
+ */
+ private Collection<Map<String, Object>> propertyMaps;
+
+ /**
+ * Constructor.
+ *
+ * @param propertyMaps collection of property maps
+ */
+ public Result(Collection<Map<String, Object>> propertyMaps) {
+ this.propertyMaps = propertyMaps;
+ }
+
+ /**
+ * Obtain the result property maps.
+ *
+ * @return result property maps
+ */
+ public Collection<Map<String, Object>> getPropertyMaps() {
+ return propertyMaps;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/TaxonomyResourceProvider.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/TaxonomyResourceProvider.java b/catalog/src/main/java/org/apache/atlas/catalog/TaxonomyResourceProvider.java
new file mode 100644
index 0000000..7a46f5d
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/TaxonomyResourceProvider.java
@@ -0,0 +1,80 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.definition.TaxonomyResourceDefinition;
+import org.apache.atlas.catalog.exception.*;
+import org.apache.atlas.catalog.query.AtlasQuery;
+
+import java.util.*;
+
+/**
+ * Provider for taxonomy resources.
+ */
+public class TaxonomyResourceProvider extends BaseResourceProvider implements ResourceProvider {
+ private static final ResourceDefinition resourceDefinition = new TaxonomyResourceDefinition();
+ public TaxonomyResourceProvider(AtlasTypeSystem typeSystem) {
+ super(typeSystem);
+ }
+
+ @Override
+ public Result getResourceById(Request request) throws ResourceNotFoundException {
+ AtlasQuery atlasQuery;
+ try {
+ atlasQuery = queryFactory.createTaxonomyQuery(request);
+ } catch (InvalidQueryException e) {
+ throw new CatalogRuntimeException("Unable to compile internal Taxonomy query: " + e, e);
+ }
+ Collection<Map<String, Object>> results = atlasQuery.execute();
+ if (results.isEmpty()) {
+ throw new ResourceNotFoundException(String.format("Taxonomy '%s' not found.",
+ request.getProperty(resourceDefinition.getIdPropertyName())));
+ }
+ return new Result(results);
+ }
+
+ public Result getResources(Request request) throws InvalidQueryException, ResourceNotFoundException {
+ AtlasQuery atlasQuery = queryFactory.createTaxonomyQuery(request);
+ return new Result(atlasQuery.execute());
+ }
+
+ public synchronized void createResource(Request request)
+ throws InvalidPayloadException, ResourceAlreadyExistsException {
+
+ resourceDefinition.validate(request);
+ ensureTaxonomyDoesntExist(request);
+ typeSystem.createEntity(resourceDefinition, request);
+ }
+
+ @Override
+ public Collection<String> createResources(Request request) throws InvalidQueryException, ResourceNotFoundException {
+ throw new UnsupportedOperationException("Creating multiple Taxonomies in a request is not currently supported");
+ }
+
+ private void ensureTaxonomyDoesntExist(Request request) throws ResourceAlreadyExistsException {
+ try {
+ getResourceById(request);
+ throw new ResourceAlreadyExistsException(String.format("Taxonomy '%s' already exists.",
+ request.getProperty("name")));
+ } catch (ResourceNotFoundException e) {
+ // expected case
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/TermPath.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/TermPath.java b/catalog/src/main/java/org/apache/atlas/catalog/TermPath.java
new file mode 100644
index 0000000..3252227
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/TermPath.java
@@ -0,0 +1,111 @@
+/**
+ * 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.catalog;
+
+/**
+ * Term path information.
+ */
+//todo: split between Term and TermPath
+public class TermPath {
+ private final String m_taxonomy;
+ private final String m_fqn;
+ private final String m_name;
+ private final String[] m_paths;
+
+ public TermPath(String fullyQualifiedName) {
+ m_fqn = fullyQualifiedName;
+ //todo: validation
+ int idx = fullyQualifiedName.indexOf('.');
+ if (idx != -1) {
+ m_taxonomy = fullyQualifiedName.substring(0, idx);
+ m_name = fullyQualifiedName.substring(idx + 1);
+ m_paths = m_name.split("\\.");
+ } else {
+ m_taxonomy = fullyQualifiedName;
+ m_name = null;
+ m_paths = new String[0];
+ }
+ }
+
+ public TermPath(String taxonomyName, String termName) {
+ m_taxonomy = taxonomyName;
+ m_name = termName != null && termName.isEmpty() ? null : termName;
+
+ if (m_name != null) {
+ m_fqn = String.format("%s.%s", taxonomyName, termName);
+ m_paths = termName.split("\\.");
+ } else {
+ m_fqn = taxonomyName;
+ m_paths = new String[0];
+ }
+ }
+
+ /**
+ * Get the absolute term name which is in the form of TAXONOMY_NAME.TERM_NAME
+ *
+ * @return absolute term name which includes the taxonomy name
+ */
+ public String getFullyQualifiedName() {
+ return m_fqn;
+ }
+
+ /**
+ * Get the term name. This differs from the absolute name in that it doesn't
+ * include the taxonomy name.
+ *
+ * @return the term name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * Get the short name for the term which doesn't include any taxonomy or parent information.
+ * @return term short name
+ */
+ public String getShortName() {
+ return m_paths[m_paths.length - 1];
+ }
+
+ public String getPath() {
+ if (m_name == null) {
+ return "/";
+ } else {
+ int idx = m_fqn.indexOf('.');
+ int lastIdx = m_fqn.lastIndexOf('.');
+
+ return idx == lastIdx ? "/" :
+ m_fqn.substring(idx, lastIdx).replaceAll("\\.", "/");
+ }
+ }
+
+ public TermPath getParent() {
+ //todo: if this is the root path, throw exception
+ return new TermPath(m_taxonomy, m_name.substring(0, m_name.lastIndexOf('.')));
+ }
+
+
+ public String getTaxonomyName() {
+ return m_taxonomy;
+ }
+
+ public String[] getPathSegments() {
+ return m_paths;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/TermResourceProvider.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/TermResourceProvider.java b/catalog/src/main/java/org/apache/atlas/catalog/TermResourceProvider.java
new file mode 100644
index 0000000..431b06d
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/TermResourceProvider.java
@@ -0,0 +1,128 @@
+/**
+ * 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.catalog;
+
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.catalog.definition.TermResourceDefinition;
+import org.apache.atlas.catalog.exception.*;
+import org.apache.atlas.catalog.query.AtlasQuery;
+
+import java.util.*;
+
+/**
+ * Provider for Term resources.
+ */
+public class TermResourceProvider extends BaseResourceProvider implements ResourceProvider {
+ private final static ResourceDefinition resourceDefinition = new TermResourceDefinition();
+ private TaxonomyResourceProvider taxonomyResourceProvider;
+
+ public TermResourceProvider(AtlasTypeSystem typeSystem) {
+ super(typeSystem);
+ }
+
+ @Override
+ public Result getResourceById(Request request) throws ResourceNotFoundException {
+ //todo: shouldn't need to add this here
+ request.getProperties().put("name", request.<TermPath>getProperty("termPath").getFullyQualifiedName());
+ AtlasQuery atlasQuery;
+ try {
+ atlasQuery = queryFactory.createTermQuery(request);
+ } catch (InvalidQueryException e) {
+ throw new CatalogRuntimeException("Unable to compile internal Term query: " + e, e);
+ }
+ Collection<Map<String, Object>> results = atlasQuery.execute();
+ if (results.isEmpty()) {
+ throw new ResourceNotFoundException(String.format("Term '%s' not found.",
+ request.<TermPath>getProperty("termPath").getFullyQualifiedName()));
+ }
+ return new Result(results);
+ }
+
+ public Result getResources(Request request)
+ throws InvalidQueryException, ResourceNotFoundException {
+
+ TermPath termPath = request.getProperty("termPath");
+ String queryString = doQueryStringConversions(termPath, request.getQueryString());
+ Request queryRequest = new CollectionRequest(request.getProperties(), queryString);
+ AtlasQuery atlasQuery = queryFactory.createTermQuery(queryRequest);
+ Collection<Map<String, Object>> result = atlasQuery.execute();
+ return new Result(result);
+ }
+
+ public void createResource(Request request)
+ throws InvalidPayloadException, ResourceAlreadyExistsException, ResourceNotFoundException {
+
+ TermPath termPath = (TermPath) request.getProperties().remove("termPath");
+ String qualifiedTermName = termPath.getFullyQualifiedName();
+ request.getProperties().put("name", qualifiedTermName);
+ resourceDefinition.validate(request);
+
+ // get taxonomy
+ Request taxonomyRequest = new InstanceRequest(
+ Collections.<String, Object>singletonMap("name", termPath.getTaxonomyName()));
+ taxonomyRequest.addAdditionalSelectProperties(Collections.singleton("id"));
+ Result taxonomyResult = getTaxonomyResourceProvider().getResourceById(taxonomyRequest);
+ Map<String, Object> taxonomyPropertyMap = taxonomyResult.getPropertyMaps().iterator().next();
+
+ // ensure that parent exists if not a root level term
+ if (! termPath.getPath().equals("/")) {
+ Map<String, Object> parentProperties = new HashMap<>(request.getProperties());
+ parentProperties.put("termPath", termPath.getParent());
+ getResourceById(new InstanceRequest(parentProperties));
+ }
+
+ typeSystem.createTraitType(resourceDefinition, qualifiedTermName,
+ request.<String>getProperty("description"));
+
+ typeSystem.createTraitInstance(String.valueOf(taxonomyPropertyMap.get("id")),
+ qualifiedTermName, request.getProperties());
+ }
+
+ @Override
+ public Collection<String> createResources(Request request) throws InvalidQueryException, ResourceNotFoundException {
+ throw new UnsupportedOperationException("Creating multiple Terms in a request is not currently supported");
+ }
+
+ //todo: add generic support for pre-query modification of expected value
+ //todo: similar path parsing code is used in several places in this class
+ private String doQueryStringConversions(TermPath termPath, String queryStr) throws InvalidQueryException {
+ String hierarchyPathProp = "hierarchy/path";
+ // replace "."
+ if (queryStr != null && queryStr.contains(String.format("%s:.", hierarchyPathProp))) {
+ //todo: regular expression replacement
+ queryStr = queryStr.replaceAll(String.format("%s:.", hierarchyPathProp),
+ String.format("%s:%s", hierarchyPathProp, termPath.getPath()));
+ }
+ return queryStr;
+ }
+
+ protected synchronized ResourceProvider getTaxonomyResourceProvider() {
+ if (taxonomyResourceProvider == null) {
+ taxonomyResourceProvider = new TaxonomyResourceProvider(typeSystem);
+ }
+ return taxonomyResourceProvider;
+ }
+}
+
+
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/TermVertexWrapper.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/TermVertexWrapper.java b/catalog/src/main/java/org/apache/atlas/catalog/TermVertexWrapper.java
new file mode 100644
index 0000000..d60e3f3
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/TermVertexWrapper.java
@@ -0,0 +1,36 @@
+/**
+ * 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.catalog;
+
+import com.tinkerpop.blueprints.Vertex;
+import org.apache.atlas.catalog.definition.EntityTagResourceDefinition;
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.repository.Constants;
+
+import java.util.Collections;
+
+/**
+ * Wrapper for term vertices.
+ */
+public class TermVertexWrapper extends VertexWrapper {
+
+ public TermVertexWrapper(Vertex v) {
+ super(v, new EntityTagResourceDefinition());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aaf2971a/catalog/src/main/java/org/apache/atlas/catalog/VertexWrapper.java
----------------------------------------------------------------------
diff --git a/catalog/src/main/java/org/apache/atlas/catalog/VertexWrapper.java b/catalog/src/main/java/org/apache/atlas/catalog/VertexWrapper.java
new file mode 100644
index 0000000..6e5d28e
--- /dev/null
+++ b/catalog/src/main/java/org/apache/atlas/catalog/VertexWrapper.java
@@ -0,0 +1,111 @@
+/**
+ * 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.catalog;
+
+import com.tinkerpop.blueprints.Vertex;
+import org.apache.atlas.catalog.definition.ResourceDefinition;
+import org.apache.atlas.repository.Constants;
+
+import java.util.*;
+
+/**
+ * Wrapper for vertices which provides additional information.
+ */
+public class VertexWrapper {
+ private final Vertex vertex;
+ private final String vertexType;
+ private final Set<String> removedProperties = new HashSet<>();
+ private final PropertyMapper propertyMapper;
+ private final Map<String, PropertyValueFormatter> propertyValueFormatters;
+ protected ResourceComparator resourceComparator = new ResourceComparator();
+
+ public VertexWrapper(Vertex v, ResourceDefinition resourceDefinition) {
+ this(v, resourceDefinition.getPropertyMapper(), resourceDefinition.getPropertyValueFormatters());
+ }
+
+ public VertexWrapper(Vertex v,
+ PropertyMapper mapper,
+ Map<String, PropertyValueFormatter> formatters) {
+ vertex = v;
+ vertexType = getVertexType(v);
+ propertyMapper = mapper;
+ propertyValueFormatters = formatters;
+ }
+
+ public Vertex getVertex() {
+ return vertex;
+ }
+
+ public <T> T getProperty(String name) {
+ T val;
+ if (removedProperties.contains(name)) {
+ val = null;
+ } else {
+ val = vertex.getProperty(propertyMapper.toFullyQualifiedName(name, vertexType));
+ if (propertyValueFormatters.containsKey(name)) {
+ //todo: fix typing of property mapper
+ val = (T) propertyValueFormatters.get(name).format(val);
+ }
+ }
+ return val;
+ }
+
+ public Collection<String> getPropertyKeys() {
+ Collection<String> propertyKeys = new TreeSet<>(resourceComparator);
+
+ for (String p : vertex.getPropertyKeys()) {
+ String cleanName = propertyMapper.toCleanName(p, vertexType);
+ if (! removedProperties.contains(cleanName)) {
+ propertyKeys.add(cleanName);
+ }
+ }
+ return propertyKeys;
+ }
+
+ public Map<String, Object> getPropertyMap() {
+ Map<String, Object> props = new TreeMap<>(resourceComparator);
+ for (String p : vertex.getPropertyKeys()) {
+ String cleanName = propertyMapper.toCleanName(p, vertexType);
+ if (! removedProperties.contains(cleanName)) {
+ Object val = vertex.getProperty(p);
+ if (propertyValueFormatters.containsKey(cleanName)) {
+ val = propertyValueFormatters.get(cleanName).format(val);
+ }
+ props.put(cleanName, val);
+ }
+ }
+ return props;
+ }
+
+ public void removeProperty(String name) {
+ removedProperties.add(name);
+ }
+
+ public boolean isPropertyRemoved(String name) {
+ return removedProperties.contains(name);
+ }
+
+ public String toString() {
+ return String.format("VertexWrapper[name=%s]", getProperty("name"));
+ }
+
+ private String getVertexType(Vertex v) {
+ return v.getProperty(Constants.ENTITY_TYPE_PROPERTY_KEY);
+ }
+}