ATLAS-2534: Atlas Glossary - REST API Change-Id: I47210446be9e38c274bae0ee4a688187ba6e4fd0 Signed-off-by: Madhan Neethiraj <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/75415862 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/75415862 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/75415862 Branch: refs/heads/master Commit: 75415862cc2708ee866d2d29ca603a4e6306f408 Parents: 6812a7d Author: apoorvnaik <[email protected]> Authored: Wed Mar 14 21:03:37 2018 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Mon Apr 9 23:06:36 2018 -0700 ---------------------------------------------------------------------- .../models/0000-Area0/0011-glossary_model.json | 880 +++++++++++++ .../repository/graphdb/AtlasGraphQuery.java | 11 + .../query/NativeTinkerpopGraphQuery.java | 8 + .../tinkerpop/query/TinkerpopGraphQuery.java | 11 +- .../tinkerpop/query/expr/OrderByPredicate.java | 41 + .../graphdb/janus/AtlasJanusGraph.java | 41 +- .../janus/query/NativeJanusGraphQuery.java | 8 + .../titan0/query/NativeTitan0GraphQuery.java | 13 +- .../java/org/apache/atlas/AtlasErrorCode.java | 6 +- .../atlas/model/AtlasBaseModelObject.java | 37 +- .../atlas/model/annotation/AtlasJSON.java | 36 + .../atlas/model/glossary/AtlasGlossary.java | 222 ++++ .../model/glossary/AtlasGlossaryBaseObject.java | 129 ++ .../model/glossary/AtlasGlossaryCategory.java | 174 +++ .../atlas/model/glossary/AtlasGlossaryTerm.java | 453 +++++++ .../enums/AtlasTermAssignmentStatus.java | 39 + .../enums/AtlasTermRelationshipStatus.java | 37 + .../glossary/relations/AtlasGlossaryHeader.java | 79 ++ .../relations/AtlasRelatedCategoryHeader.java | 93 ++ .../relations/AtlasRelatedTermHeader.java | 139 +++ .../relations/AtlasTermAssignmentHeader.java | 162 +++ .../AtlasTermCategorizationHeader.java | 107 ++ .../atlas/model/instance/AtlasEntity.java | 31 +- .../atlas/model/instance/AtlasEntityHeader.java | 95 +- .../atlas/model/instance/AtlasRelationship.java | 3 - .../atlas/type/AtlasRelationshipType.java | 2 - .../apache/atlas/glossary/GlossaryService.java | 1159 ++++++++++++++++++ .../ogm/AbstractDataTransferObject.java | 20 +- .../repository/ogm/AtlasSavedSearchDTO.java | 105 -- .../repository/ogm/AtlasUserProfileDTO.java | 115 -- .../atlas/repository/ogm/DTORegistry.java | 21 +- .../apache/atlas/repository/ogm/DataAccess.java | 196 ++- .../ogm/glossary/AbstractGlossaryDTO.java | 163 +++ .../ogm/glossary/AtlasGlossaryCategoryDTO.java | 159 +++ .../ogm/glossary/AtlasGlossaryDTO.java | 155 +++ .../ogm/glossary/AtlasGlossaryTermDTO.java | 250 ++++ .../ogm/profiles/AtlasSavedSearchDTO.java | 110 ++ .../ogm/profiles/AtlasUserProfileDTO.java | 120 ++ .../graph/v1/AtlasEntityChangeNotifier.java | 6 +- .../store/graph/v1/AtlasGraphUtilsV1.java | 20 +- .../store/graph/v1/EntityGraphRetriever.java | 9 + .../userprofile/UserProfileService.java | 4 +- .../test/java/org/apache/atlas/TestModules.java | 25 +- .../atlas/glossary/GlossaryServiceTest.java | 641 ++++++++++ .../atlas/glossary/PaginationHelperTest.java | 64 + .../impexp/ZipFileResourceTestUtils.java | 42 +- .../userprofile/UserProfileServiceTest.java | 10 +- .../EntityNotificationListenerV2.java | 35 +- .../org/apache/atlas/web/rest/GlossaryREST.java | 839 +++++++++++++ 49 files changed, 6735 insertions(+), 390 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/addons/models/0000-Area0/0011-glossary_model.json ---------------------------------------------------------------------- diff --git a/addons/models/0000-Area0/0011-glossary_model.json b/addons/models/0000-Area0/0011-glossary_model.json new file mode 100644 index 0000000..ae7e5c7 --- /dev/null +++ b/addons/models/0000-Area0/0011-glossary_model.json @@ -0,0 +1,880 @@ +{ + "enumDefs": [ + { + "name": "__AtlasGlossaryTermRelationshipStatus", + "description": "TermRelationshipStatus defines how reliable the relationship is between two glossary terms", + "typeVersion": "1.0", + "elementDefs": [ + { + "ordinal": 0, + "value": "DRAFT", + "description": "DRAFT means the relationship is under development." + }, + { + "ordinal": 1, + "value": "ACTIVE", + "description": "ACTIVE means the relationship is validated and in use." + }, + { + "ordinal": 2, + "value": "DEPRECATED", + "description": "DEPRECATED means the the relationship is being phased out." + }, + { + "ordinal": 3, + "value": "OBSOLETE", + "description": "OBSOLETE means that the relationship should not be used anymore." + }, + { + "ordinal": 99, + "value": "OTHER", + "description": "OTHER means that there is another status." + } + ] + }, + { + "name": "__AtlasGlossaryTermAssignmentStatus", + "description": "TermAssignmentStatus defines how much the semantic assignment should be trusted.", + "typeVersion": "1.0", + "elementDefs": [ + { + "value": "DISCOVERED", + "ordinal": 0, + "description": "DISCOVERED means that the semantic assignment was added by a discovery engine." + }, + { + "value": "PROPOSED", + "ordinal": 1, + "description": "PROPOSED means that the semantic assignment was proposed by person - they may be a subject matter expert, or consumer of the Referenceable asset" + }, + { + "value": "IMPORTED", + "ordinal": 2, + "description": "IMPORTED means that the semantic assignment has been imported from outside of the open metadata cluster" + }, + { + "value": "VALIDATED", + "ordinal": 3, + "description": "VALIDATED means that the semantic assignment has been reviewed and is highly trusted." + }, + { + "value": "DEPRECATED", + "ordinal": 4, + "description": "DEPRECATED means that the semantic assignment is being phased out. There may be another semantic assignment to the Referenceable that will ultimately replace this one." + }, + { + "value": "OBSOLETE", + "ordinal": 5, + "description": "OBSOLETE means that the semantic assignment is no longer in use," + }, + { + "value": "OTHER", + "ordinal": 6, + "description": "OTHER means that the semantic assignment value does not match any of the other Term Assignment Status values" + } + ] + } + ], + "structDefs": [], + "classificationDefs": [], + "entityDefs": [ + { + "name": "__AtlasGlossary", + "superTypes": [ + "__internal" + ], + "typeVersion": "1.0", + "attributeDefs": [ + { + "name": "qualifiedName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": true + }, + { + "name": "displayName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false + }, + { + "name": "shortDescription", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "longDescription", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "language", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "usage", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + } + ] + }, + { + "name": "__AtlasGlossaryTerm", + "superTypes": [ + "__internal" + ], + "typeVersion": "1.0", + "attributeDefs": [ + { + "name": "qualifiedName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": true + }, + { + "name": "displayName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false + }, + { + "name": "shortDescription", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "longDescription", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "examples", + "typeName": "array<string>", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "abbreviation", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "usage", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + } + ] + }, + { + "name": "__AtlasGlossaryCategory", + "superTypes": [ + "__internal" + ], + "typeVersion": "1.0", + "attributeDefs": [ + { + "name": "qualifiedName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": true + }, + { + "name": "displayName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false + }, + { + "name": "shortDescription", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "longDescription", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + } + ] + } + ], + "relationshipDefs": [ + { + "name": "__AtlasGlossarySemanticAssignment", + "description": "SemanticAssignment is a relationship used to assign a term to a referenceable object. This means that the term describes the meaning of the referenceable object. The semantic assignment needs to be a controlled relationship when glossary definitions are used to provide classifications for the data assets and hence define how the data is to be governed.", + "typeVersion": "1.0", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the semantic assignment.", + "typeName": "string", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + }, + { + "name": "expression", + "typeName": "string", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + }, + { + "name": "confidence", + "description": "The confidence attribute in the semantic assignment stores the level of confidence (0-100%) in the correctness of the semantic assignment - it is typically used by discovery engines.", + "typeName": "int", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + }, + { + "name": "createdBy", + "description": "The semantic assignment is created by the user (person or engine) identified by the createdBy attribute.", + "typeName": "string", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the semantic assignment and deciding if it should be approved or not.", + "typeName": "string", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + }, + { + "name": "source", + "typeName": "string", + "isOptional": true, + "cardinality": "SINGLE", + "valuesMinCount": 0, + "valuesMaxCount": 1, + "isUnique": false, + "isIndexable": true + } + ], + "relationshipCategory": "ASSOCIATION", + "propagateTags": "ONE_TO_TWO", + "endDef1": { + "type": "__AtlasGlossaryTerm", + "name": "assignedEntities", + "isContainer": false, + "cardinality": "SET" + }, + "endDef2": { + "type": "Referenceable", + "name": "meanings", + "isContainer": false, + "cardinality": "SET" + } + }, + { + "name": "__AtlasGlossaryTermAnchor", + "typeVersion": "1.0", + "description": "TermAnchor links each term to exactly one Glossary object. This means that this is its home glossary. If the Glossary object is deleted, then so are all of the terms linked to it.", + "endDef1": { + "name": "terms", + "type": "__AtlasGlossary", + "cardinality": "SET", + "isContainer": true + }, + "endDef2": { + "name": "anchor", + "type": "__AtlasGlossaryTerm", + "cardinality": "SINGLE" + }, + "relationshipCategory": "COMPOSITION", + "propagateTags": "NONE" + }, + { + "name": "__AtlasGlossaryTermCategorization", + "typeVersion": "1.0", + "description": "TermCategorization is a relationship used to organize terms into categories. A term may be linked with many categories and a category may have many terms linked to it. This relationship may connect terms and categories both in the same glossary or in different glossaries.", + "endDef1": { + "name": "terms", + "type": "__AtlasGlossaryCategory", + "cardinality": "SET", + "isContainer": true + }, + "endDef2": { + "name": "categories", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "AGGREGATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false + } + ] + }, + { + "name": "__AtlasGlossaryCategoryAnchor", + "typeVersion": "1.0", + "description": "CategoryAnchor links each category to exactly one Glossary object. This means that this is its home glossary. If the Glossary object is deleted then so are all of the categories linked to it.", + "endDef1": { + "name": "categories", + "type": "__AtlasGlossary", + "cardinality": "SET", + "isContainer": true + }, + "endDef2": { + "name": "anchor", + "type": "__AtlasGlossaryCategory", + "cardinality": "SINGLE" + }, + "relationshipCategory": "COMPOSITION", + "propagateTags": "NONE" + }, + { + "name": "__AtlasGlossaryCategoryHierarchyLink", + "typeVersion": "1.0", + "description": "CategoryHierarchyLink is a relationship used to organize categories into a hierarchy to, for example, create a structure for a taxonomy. A category may have none or one super-categories. This super-category may be in a different glossary.", + "endDef1": { + "name": "childrenCategories", + "type": "__AtlasGlossaryCategory", + "cardinality": "SET", + "isContainer": true + }, + "endDef2": { + "name": "parentCategory", + "type": "__AtlasGlossaryCategory", + "cardinality": "SINGLE" + }, + "relationshipCategory": "AGGREGATION", + "propagateTags": "NONE" + }, + { + "name": "__AtlasGlossaryRelatedTerm", + "typeVersion": "1.0", + "description": "RelatedTerm is a relationship used to say that the linked glossary term may also be of interest. It is like a 'see also' link in a dictionary.", + "endDef1": { + "name": "seeAlso", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "seeAlso", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to explain why the linked term is of interest.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossarySynonym", + "typeVersion": "1.0", + "description": "Synonym is a relationship between glossary terms that have the same, or a very similar meaning in the same language. Notice that both ends of this relationship have the same name and refer to the same type; this results in one Synonym attribute being added to GlossaryTerm.", + "endDef1": { + "name": "synonyms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "synonyms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossaryAntonym", + "typeVersion": "1.0", + "description": "Antonym is a relationship between glossary terms that have the opposite (or near opposite) meaning, in the same language. Notice that both ends of this relationship have the same name and refer to the same type; this results in one Antonym attribute being added to GlossaryTerm.", + "endDef1": { + "name": "antonyms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "antonyms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossaryPreferredTerm", + "typeVersion": "1.0", + "description": "PreferredTerm is a relationship that indicates that the preferredTerm should be used in place of the preferredToTerm. This relationship can be used to encourage adoption of newer vocabularies. This is a weaker version of ReplacementTerm.", + "endDef1": { + "name": "preferredTerms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "preferredToTerms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossaryReplacementTerm", + "typeVersion": "1.0", + "description": "ReplacementTerm is a relationship that indicates that the replacementTerm must be used instead of the replacedByTerm. This is stronger version of the PreferredTerm.", + "endDef1": { + "name": "replacedBy", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "replacementTerms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossaryTranslation", + "typeVersion": "1.0", + "description": "Translation is a relationship that defines that the related terms represent the same meaning, but each are written in a different language. Hence one is a translation of the other. The language of each term is defined in the Glossary object that anchors the term.", + "endDef1": { + "name": "translatedTerms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "translationTerms", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossaryIsARelationship", + "typeVersion": "1.0", + "description": "IsA is a relationship that defines that the 'isA' term is a more generic term than the 'isOf' term. For example, this relationship would be use to say that 'Cat' ISA 'Animal'.", + "endDef1": { + "name": "classifies", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "isA", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + }, + { + "name": "__AtlasGlossaryValidValue", + "typeVersion": "1.0", + "description": "ValidValue is a relationship that shows the validValue term represents one of the valid values that could be assigned to a data item that has the meaning described in the validValueFor term.", + "endDef1": { + "name": "validValuesFor", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "endDef2": { + "name": "validValues", + "type": "__AtlasGlossaryTerm", + "cardinality": "SET" + }, + "relationshipCategory": "ASSOCIATION", + "propagateTags": "NONE", + "attributeDefs": [ + { + "name": "description", + "description": "The description field can be used to add details about the relationship.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "expression", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "status", + "typeName": "__AtlasGlossaryTermRelationshipStatus", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "steward", + "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + }, + { + "name": "source", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true + } + ] + } + ] +} http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java index 7bdbeab..883a31b 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java @@ -30,6 +30,8 @@ import java.util.List; */ public interface AtlasGraphQuery<V, E> { + enum SortOrder { ASC, DESC } + /** * Adds a predicate that the returned vertices must have the specified * property and that one of the values of the property must be the @@ -106,6 +108,15 @@ public interface AtlasGraphQuery<V, E> { */ AtlasGraphQuery<V, E> has(String propertyKey, QueryOperator op, Object values); + + /** + * Adds a sorting predicate + * @param propertyKey property key to sort on + * @param order ASC or DESC + * @return + */ + AtlasGraphQuery<V, E> orderBy(String propertyKey, SortOrder order); + /** * Adds a predicate that the vertices returned must satisfy the * conditions in at least one of the child queries provided. http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/NativeTinkerpopGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/NativeTinkerpopGraphQuery.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/NativeTinkerpopGraphQuery.java index 7566559..19ec5e4 100644 --- a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/NativeTinkerpopGraphQuery.java +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/NativeTinkerpopGraphQuery.java @@ -18,6 +18,7 @@ package org.apache.atlas.repository.graphdb.tinkerpop.query; import org.apache.atlas.repository.graphdb.AtlasEdge; +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; import org.apache.atlas.repository.graphdb.AtlasGraphQuery.QueryOperator; import org.apache.atlas.repository.graphdb.AtlasVertex; @@ -93,4 +94,11 @@ public interface NativeTinkerpopGraphQuery<V, E> { * @param value */ void has(String propertyName, QueryOperator op, Object value); + + /** + * Add sort predicate for give property + * @param propertyName + * @param sortOrder + */ + void orderBy(String propertyName, AtlasGraphQuery.SortOrder sortOrder); } http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/TinkerpopGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/TinkerpopGraphQuery.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/TinkerpopGraphQuery.java index 96b9705..d680654 100644 --- a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/TinkerpopGraphQuery.java +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/TinkerpopGraphQuery.java @@ -26,11 +26,13 @@ import org.apache.atlas.repository.graphdb.tinkerpop.query.expr.AndCondition; import org.apache.atlas.repository.graphdb.tinkerpop.query.expr.HasPredicate; import org.apache.atlas.repository.graphdb.tinkerpop.query.expr.InPredicate; import org.apache.atlas.repository.graphdb.tinkerpop.query.expr.OrCondition; +import org.apache.atlas.repository.graphdb.tinkerpop.query.expr.OrderByPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -129,7 +131,8 @@ public abstract class TinkerpopGraphQuery<V, E> implements AtlasGraphQuery<V, E> } // Compute the overall result by combining the results of all the AndConditions (nested within OR) together. - Set<AtlasVertex<V, E>> result = new HashSet<>(); + Set<AtlasVertex<V, E>> result = new LinkedHashSet<>(); + for(AndCondition andExpr : queryCondition.getAndTerms()) { NativeTinkerpopGraphQuery<V, E> andQuery = andExpr.create(getQueryFactory()); for(AtlasVertex<V, E> vertex : andQuery.vertices()) { @@ -269,6 +272,12 @@ public abstract class TinkerpopGraphQuery<V, E> implements AtlasGraphQuery<V, E> return this; } + @Override + public AtlasGraphQuery<V, E> orderBy(final String propertyKey, final SortOrder order) { + queryCondition.andWith(new OrderByPredicate(propertyKey, order)); + return this; + } + private OrCondition getOrCondition() { return queryCondition; } http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/expr/OrderByPredicate.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/expr/OrderByPredicate.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/expr/OrderByPredicate.java new file mode 100644 index 0000000..8ba97af --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/tinkerpop/query/expr/OrderByPredicate.java @@ -0,0 +1,41 @@ +/** + * 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.repository.graphdb.tinkerpop.query.expr; + +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; +import org.apache.atlas.repository.graphdb.tinkerpop.query.NativeTinkerpopGraphQuery; + +public class OrderByPredicate implements QueryPredicate { + private final String propertyKey; + private final AtlasGraphQuery.SortOrder sortOrder; + + public OrderByPredicate(final String propertyKey, final AtlasGraphQuery.SortOrder sortOrder) { + this.propertyKey = propertyKey; + this.sortOrder = sortOrder; + } + + @Override + public void addTo(final NativeTinkerpopGraphQuery query) { + query.orderBy(propertyKey, sortOrder); + } + + @Override + public String toString() { + return "OrderBy [ propertyKey = " + propertyKey + ", order = " + sortOrder + " ]"; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java ---------------------------------------------------------------------- diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java index fdef800..2a1ce4e 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java @@ -18,22 +18,11 @@ package org.apache.atlas.repository.graphdb.janus; import com.google.common.base.Function; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasException; -import org.apache.atlas.type.AtlasType; -import org.apache.commons.configuration.Configuration; -import org.janusgraph.core.Cardinality; -import org.janusgraph.core.JanusGraphFactory; -import org.janusgraph.core.PropertyKey; -import org.janusgraph.core.SchemaViolationException; -import org.janusgraph.core.JanusGraph; -import org.janusgraph.core.JanusGraphIndexQuery; -import org.janusgraph.core.schema.JanusGraphIndex; -import org.janusgraph.core.schema.JanusGraphManagement; import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.AtlasException; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.groovy.GroovyExpression; import org.apache.atlas.repository.graphdb.AtlasEdge; @@ -46,6 +35,8 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.GremlinVersion; import org.apache.atlas.repository.graphdb.janus.query.AtlasJanusGraphQuery; import org.apache.atlas.repository.graphdb.utils.IteratorToIterableAdapter; +import org.apache.atlas.type.AtlasType; +import org.apache.commons.configuration.Configuration; import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; @@ -58,6 +49,14 @@ import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.io.IoCore; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter; +import org.janusgraph.core.Cardinality; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphFactory; +import org.janusgraph.core.JanusGraphIndexQuery; +import org.janusgraph.core.PropertyKey; +import org.janusgraph.core.SchemaViolationException; +import org.janusgraph.core.schema.JanusGraphIndex; +import org.janusgraph.core.schema.JanusGraphManagement; import org.janusgraph.diskstorage.BackendException; import javax.script.Bindings; @@ -72,6 +71,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import static org.apache.atlas.repository.Constants.INDEX_SEARCH_VERTEX_PREFIX_DEFAULT; import static org.apache.atlas.repository.Constants.INDEX_SEARCH_VERTEX_PREFIX_PROPERTY; @@ -406,13 +407,7 @@ public class AtlasJanusGraph implements AtlasGraph<AtlasJanusVertex, AtlasJanusE public Iterable<AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>> wrapVertices(Iterable<? extends Vertex> it) { - return Iterables.transform(it, new Function<Vertex, AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>>() { - - @Override - public AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> apply(Vertex input) { - return GraphDbObjectFactory.createVertex(AtlasJanusGraph.this, input); - } - }); + return StreamSupport.stream(it.spliterator(), false).map(input -> GraphDbObjectFactory.createVertex(AtlasJanusGraph.this, input)).collect(Collectors.toList()); } @@ -423,13 +418,7 @@ public class AtlasJanusGraph implements AtlasGraph<AtlasJanusVertex, AtlasJanusE public Iterable<AtlasEdge<AtlasJanusVertex, AtlasJanusEdge>> wrapEdges(Iterable<? extends Edge> it) { - return Iterables.transform(it, new Function<Edge, AtlasEdge<AtlasJanusVertex, AtlasJanusEdge>>() { - - @Override - public AtlasEdge<AtlasJanusVertex, AtlasJanusEdge> apply(Edge input) { - return GraphDbObjectFactory.createEdge(AtlasJanusGraph.this, input); - } - }); + return StreamSupport.stream(it.spliterator(), false).map(input -> GraphDbObjectFactory.createEdge(AtlasJanusGraph.this, input)).collect(Collectors.toList()); } http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java index d3c976d..d63e1d7 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java @@ -17,6 +17,8 @@ */ package org.apache.atlas.repository.graphdb.janus.query; +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; +import org.apache.tinkerpop.gremlin.process.traversal.Order; import org.apache.tinkerpop.gremlin.structure.Edge; import org.janusgraph.core.JanusGraphEdge; import org.janusgraph.core.JanusGraphQuery; @@ -126,6 +128,12 @@ public class NativeJanusGraphQuery implements NativeTinkerpopGraphQuery<AtlasJan query.has(propertyName, pred, value); } + @Override + public void orderBy(final String propertyName, final AtlasGraphQuery.SortOrder sortOrder) { + Order order = sortOrder == AtlasGraphQuery.SortOrder.ASC ? Order.incr : Order.decr; + query.orderBy(propertyName, order); + } + private Text getGremlinPredicate(MatchingOperator op) { switch (op) { case CONTAINS: http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/graphdb/titan0/src/main/java/org/apache/atlas/repository/graphdb/titan0/query/NativeTitan0GraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/titan0/src/main/java/org/apache/atlas/repository/graphdb/titan0/query/NativeTitan0GraphQuery.java b/graphdb/titan0/src/main/java/org/apache/atlas/repository/graphdb/titan0/query/NativeTitan0GraphQuery.java index 2903ae2..68a7048 100644 --- a/graphdb/titan0/src/main/java/org/apache/atlas/repository/graphdb/titan0/query/NativeTitan0GraphQuery.java +++ b/graphdb/titan0/src/main/java/org/apache/atlas/repository/graphdb/titan0/query/NativeTitan0GraphQuery.java @@ -17,7 +17,7 @@ */ package org.apache.atlas.repository.graphdb.titan0.query; -import com.google.common.collect.Lists; +import com.thinkaurelius.titan.core.Order; import com.thinkaurelius.titan.core.TitanGraphQuery; import com.thinkaurelius.titan.core.attribute.Contain; import com.thinkaurelius.titan.core.attribute.Text; @@ -26,6 +26,7 @@ import com.tinkerpop.blueprints.Compare; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Vertex; import org.apache.atlas.repository.graphdb.AtlasEdge; +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator; import org.apache.atlas.repository.graphdb.AtlasGraphQuery.MatchingOperator; import org.apache.atlas.repository.graphdb.AtlasGraphQuery.QueryOperator; @@ -36,7 +37,10 @@ import org.apache.atlas.repository.graphdb.titan0.Titan0Graph; import org.apache.atlas.repository.graphdb.titan0.Titan0GraphDatabase; import org.apache.atlas.repository.graphdb.titan0.Titan0Vertex; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; /** * Titan 0.5.4 implementation of NativeTitanGraphQuery. @@ -129,6 +133,11 @@ public class NativeTitan0GraphQuery implements NativeTinkerpopGraphQuery<Titan0V query.has(propertyName, pred, value); } + @Override + public void orderBy(final String propertyName, final AtlasGraphQuery.SortOrder sortOrder) { + query.orderBy(propertyName, sortOrder == AtlasGraphQuery.SortOrder.ASC ? Order.ASC : Order.DESC); + } + private Text getGremlinPredicate(MatchingOperator op) { switch (op) { case CONTAINS: http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java index 997ac68..3805c22 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -128,6 +128,9 @@ public enum AtlasErrorCode { NO_CLASSIFICATIONS_FOUND_FOR_ENTITY(400, "ATLAS-400-00-06E", "No classifications associated with entity: {0}"), INVALID_CLASSIFICATION_PARAMS(400, "ATLAS-400-00-06F", "Invalid classification parameters passed for {0} operation for entity: {1}"), PROPAGATED_CLASSIFICATION_NOT_ASSOCIATED_WITH_ENTITY(400, "ATLAS-400-00-070", "Propagated classification {0} is not associated with entity"), + // Glossary Related errors + INVALID_PARTIAL_UPDATE_ATTR_VAL(400, "ATLAS-400-00-071", "Invalid attrVal for partial update of {0}, expected = {1} found {2}"), + MISSING_MANDATORY_ANCHOR(400, "ATLAS-400-00-072", "Mandatory anchor attribute is missing"), UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"), @@ -148,6 +151,7 @@ public enum AtlasErrorCode { RELATIONSHIP_ALREADY_DELETED(404, "ATLAS-404-00-00F", "Attempting to delete a relationship which is already deleted : {0}"), INVALID_ENTITY_GUID_FOR_CLASSIFICATION_UPDATE(404, "ATLAS-404-00-010", "Updating entityGuid of classification is not allowed."), INSTANCE_GUID_NOT_DATASET(404, "ATLAS-404-00-011", "Given instance guid {0} is not a dataset"), + INSTANCE_GUID_DELETED(404, "ATLAS-404-00-012", "Given instance guid {0} has been deleted"), // All data conflict errors go here TYPE_ALREADY_EXISTS(409, "ATLAS-409-00-001", "Given type {0} already exists"), @@ -177,7 +181,7 @@ public enum AtlasErrorCode { HIVE_HOOK_METASTORE_BRIDGE(500, "ATLAS-500-00-011", "HiveHookMetaStoreBridge: {0}"), DATA_ACCESS_SAVE_FAILED(500, "ATLAS-500-00-012", "Save failed: {0}"), DATA_ACCESS_LOAD_FAILED(500, "ATLAS-500-00-013", "Load failed: {0}"), - ENTITY_NOTIFICATION_FAILED(500, "ATLAS-500-00-014", "Notification failed for operation: {} : {}"); + ENTITY_NOTIFICATION_FAILED(500, "ATLAS-500-00-014", "Notification failed for operation: {0} : {1}"); private String errorCode; private String errorMessage; http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/intg/src/main/java/org/apache/atlas/model/AtlasBaseModelObject.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/AtlasBaseModelObject.java b/intg/src/main/java/org/apache/atlas/model/AtlasBaseModelObject.java index 688f6f4..5f6654a 100644 --- a/intg/src/main/java/org/apache/atlas/model/AtlasBaseModelObject.java +++ b/intg/src/main/java/org/apache/atlas/model/AtlasBaseModelObject.java @@ -17,32 +17,18 @@ */ package org.apache.atlas.model; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.atlas.model.annotation.AtlasJSON; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable; +import java.util.Objects; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; - -@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) -@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown=true) -@XmlRootElement -@XmlAccessorType(XmlAccessType.PROPERTY) +@AtlasJSON public abstract class AtlasBaseModelObject implements Serializable { private static final long serialVersionUID = 1L; private String guid; - - protected AtlasBaseModelObject() { - } - + protected AtlasBaseModelObject() {} public String getGuid() { return this.guid; @@ -52,7 +38,6 @@ public abstract class AtlasBaseModelObject implements Serializable { this.guid = guid; } - @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -63,5 +48,19 @@ public abstract class AtlasBaseModelObject implements Serializable { return sb.toString(); } + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof AtlasBaseModelObject)) return false; + final AtlasBaseModelObject that = (AtlasBaseModelObject) o; + return Objects.equals(guid, that.guid); + } + + @Override + public int hashCode() { + + return Objects.hash(guid); + } + protected abstract StringBuilder toString(StringBuilder sb); } http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/intg/src/main/java/org/apache/atlas/model/annotation/AtlasJSON.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/annotation/AtlasJSON.java b/intg/src/main/java/org/apache/atlas/model/annotation/AtlasJSON.java new file mode 100644 index 0000000..03d5603 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/annotation/AtlasJSON.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.model.annotation; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown=true) +public @interface AtlasJSON {} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossary.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossary.java b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossary.java new file mode 100644 index 0000000..3c5f418 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossary.java @@ -0,0 +1,222 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.model.glossary; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.atlas.model.annotation.AtlasJSON; +import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; +import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; +import org.apache.commons.collections.CollectionUtils; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +@AtlasJSON +public class AtlasGlossary extends AtlasGlossaryBaseObject { + private String language; + private String usage; + + private Set<AtlasRelatedTermHeader> terms; + private Set<AtlasRelatedCategoryHeader> categories; + + public AtlasGlossary() { + } + + public AtlasGlossary(final AtlasGlossary other) { + super.setQualifiedName(other.getQualifiedName()); + super.setGuid(other.getGuid()); + super.setDisplayName(other.displayName); + super.setShortDescription(other.shortDescription); + super.setLongDescription(other.longDescription); + this.language = other.language; + this.usage = other.usage; + this.terms = other.terms; + this.categories = other.categories; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(final String language) { + this.language = language; + } + + public String getUsage() { + return usage; + } + + public void setUsage(final String usage) { + this.usage = usage; + } + + public Set<AtlasRelatedCategoryHeader> getCategories() { + return categories; + } + + public void setCategories(final Set<AtlasRelatedCategoryHeader> categories) { + this.categories = categories; + } + + public Set<AtlasRelatedTermHeader> getTerms() { + return terms; + } + + public void setTerms(final Set<AtlasRelatedTermHeader> terms) { + this.terms = terms; + } + + @JsonIgnore + @Override + public void setAttribute(String attrName, String attrVal) { + Objects.requireNonNull(attrName, "AtlasGlossary attribute name"); + switch (attrName) { + case "displayName": + setDisplayName(attrVal); + break; + case "shortDescription": + setShortDescription(attrVal); + break; + case "longDescription": + setLongDescription(attrVal); + break; + case "language": + setLanguage(attrVal); + break; + case "usage": + setUsage(attrVal); + break; + default: + throw new IllegalArgumentException("Invalid attribute '" + attrName + "' for object AtlasGlossary"); + } + } + + @JsonIgnore + public void addTerm(AtlasRelatedTermHeader relatedTermId) { + Set<AtlasRelatedTermHeader> terms = this.terms; + if (terms == null) { + terms = new HashSet<>(); + } + terms.add(relatedTermId); + setTerms(terms); + } + + @JsonIgnore + public void addCategory(AtlasRelatedCategoryHeader relatedCategoryId) { + Set<AtlasRelatedCategoryHeader> categories = this.categories; + if (categories == null) { + categories = new HashSet<>(); + } + categories.add(relatedCategoryId); + setCategories(categories); + } + + @JsonIgnore + public void removeTerm(AtlasRelatedTermHeader relatedTermId) { + if (CollectionUtils.isNotEmpty(terms)) { + terms.remove(relatedTermId); + } + } + + @JsonIgnore + public void removeCategory(AtlasRelatedCategoryHeader relatedCategoryId) { + if (CollectionUtils.isNotEmpty(categories)) { + categories.remove(relatedCategoryId); + } + } + + @Override + protected StringBuilder toString(final StringBuilder sb) { + return sb == null ? new StringBuilder(toString()) : sb.append(toString()); + } + + + @AtlasJSON + public static class AtlasGlossaryExtInfo extends AtlasGlossary { + private Map<String, AtlasGlossaryTerm> termInfo; + private Map<String, AtlasGlossaryCategory> categoryInfo; + + public AtlasGlossaryExtInfo() { + } + + public AtlasGlossaryExtInfo(AtlasGlossary glossary) { + super(glossary); + } + + public Map<String, AtlasGlossaryTerm> getTermInfo() { + return termInfo; + } + + public void addTermInfo(final AtlasGlossaryTerm term) { + if (termInfo == null) { + termInfo = new HashMap<>(); + } + termInfo.put(term.getGuid(), term); + } + + public void setTermInfo(final Map<String, AtlasGlossaryTerm> termInfo) { + this.termInfo = termInfo; + } + + public Map<String, AtlasGlossaryCategory> getCategoryInfo() { + return categoryInfo; + } + + public void addCategoryInfo(final AtlasGlossaryCategory category) { + if (categoryInfo == null) { + categoryInfo = new HashMap<>(); + } + categoryInfo.put(category.getGuid(), category); + } + + public void setCategoryInfo(final Map<String, AtlasGlossaryCategory> categoryInfo) { + this.categoryInfo = categoryInfo; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof AtlasGlossaryExtInfo)) return false; + if (!super.equals(o)) return false; + final AtlasGlossaryExtInfo that = (AtlasGlossaryExtInfo) o; + return Objects.equals(termInfo, that.termInfo) && + Objects.equals(categoryInfo, that.categoryInfo); + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), termInfo, categoryInfo); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("AtlasGlossaryExtInfo{"); + sb.append(super.toString()); + sb.append(", termInfo=").append(termInfo); + sb.append(", categoryInfo=").append(categoryInfo); + sb.append('}'); + return sb.toString(); + } + + + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryBaseObject.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryBaseObject.java b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryBaseObject.java new file mode 100644 index 0000000..a3e0a37 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryBaseObject.java @@ -0,0 +1,129 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.model.glossary; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.atlas.model.AtlasBaseModelObject; +import org.apache.atlas.model.instance.AtlasClassification; +import org.apache.commons.collections.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public abstract class AtlasGlossaryBaseObject extends AtlasBaseModelObject { + // Core attributes + protected String displayName; + protected String shortDescription; + protected String longDescription; + + // Classifications + protected List<AtlasClassification> classifications; + private String qualifiedName; + + public String getQualifiedName() { + return qualifiedName; + } + + public void setQualifiedName(final String qualifiedName) { + this.qualifiedName = qualifiedName; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(final String displayName) { + this.displayName = displayName; + } + + public String getShortDescription() { + return shortDescription; + } + + public void setShortDescription(final String shortDescription) { + this.shortDescription = shortDescription; + } + + public String getLongDescription() { + return longDescription; + } + + public void setLongDescription(final String longDescription) { + this.longDescription = longDescription; + } + + abstract public void setAttribute(String attrName, String attrVal); + + public List<AtlasClassification> getClassifications() { + return classifications; + } + + public void setClassifications(final List<AtlasClassification> classifications) { + this.classifications = classifications; + } + + @JsonIgnore + public void addClassification(AtlasClassification classification) { + List<AtlasClassification> classifications = this.classifications; + if (classifications == null) { + classifications = new ArrayList<>(); + } + classifications.add(classification); + setClassifications(classifications); + } + + @JsonIgnore + public void removeClassification(AtlasClassification classification) { + if (CollectionUtils.isNotEmpty(classifications)) { + classifications.remove(classification); + } + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof AtlasGlossaryBaseObject)) return false; + if (!super.equals(o)) return false; + final AtlasGlossaryBaseObject that = (AtlasGlossaryBaseObject) o; + return Objects.equals(displayName, that.displayName) && + Objects.equals(shortDescription, that.shortDescription) && + Objects.equals(longDescription, that.longDescription) && + Objects.equals(classifications, that.classifications) && + Objects.equals(qualifiedName, that.qualifiedName); + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), displayName, shortDescription, longDescription, classifications, qualifiedName); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("AtlasGlossaryBaseObject{"); + sb.append("displayName='").append(displayName).append('\''); + sb.append(", shortDescription='").append(shortDescription).append('\''); + sb.append(", longDescription='").append(longDescription).append('\''); + sb.append(", classifications=").append(classifications); + sb.append(", qualifiedName='").append(qualifiedName).append('\''); + sb.append('}'); + return sb.toString(); + } + +} http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryCategory.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryCategory.java b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryCategory.java new file mode 100644 index 0000000..55fb580 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryCategory.java @@ -0,0 +1,174 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.model.glossary; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.atlas.model.annotation.AtlasJSON; +import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader; +import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; +import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; +import org.apache.commons.collections.CollectionUtils; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +@AtlasJSON +public class AtlasGlossaryCategory extends AtlasGlossaryBaseObject { + // Inherited attributes from relations + private AtlasGlossaryHeader anchor; + + // Category hierarchy links + private AtlasRelatedCategoryHeader parentCategory; + private Set<AtlasRelatedCategoryHeader> childrenCategories; + + // Terms associated with this category + private Set<AtlasRelatedTermHeader> terms; + + public AtlasGlossaryCategory() { + } + + public AtlasGlossaryHeader getAnchor() { + return anchor; + } + + public void setAnchor(final AtlasGlossaryHeader anchor) { + this.anchor = anchor; + } + + public AtlasRelatedCategoryHeader getParentCategory() { + return parentCategory; + } + + public void setParentCategory(final AtlasRelatedCategoryHeader parentCategory) { + this.parentCategory = parentCategory; + } + + public Set<AtlasRelatedCategoryHeader> getChildrenCategories() { + return childrenCategories; + } + + public void setChildrenCategories(final Set<AtlasRelatedCategoryHeader> childrenCategories) { + this.childrenCategories = childrenCategories; + } + + public Set<AtlasRelatedTermHeader> getTerms() { + return terms; + } + + public void setTerms(final Set<AtlasRelatedTermHeader> terms) { + this.terms = terms; + } + + @JsonIgnore + public void addChild(AtlasRelatedCategoryHeader child) { + Set<AtlasRelatedCategoryHeader> children = this.childrenCategories ; + if (children == null) { + children = new HashSet<>(); + } + children.add(child); + setChildrenCategories(children); + } + + @JsonIgnore + public void removeChild(AtlasRelatedCategoryHeader child) { + if (CollectionUtils.isNotEmpty(childrenCategories)) { + childrenCategories.remove(child); + } + } + + @JsonIgnore + public void addTerm(AtlasRelatedTermHeader term) { + Set<AtlasRelatedTermHeader> terms = this.terms; + if (terms == null) { + terms = new HashSet<>(); + } + terms.add(term); + setTerms(terms); + } + + @JsonIgnore + public void removeTerm(AtlasRelatedTermHeader term) { + if (CollectionUtils.isNotEmpty(terms)) { + terms.remove(term); + } + } + + @JsonIgnore + @Override + public void setAttribute(String attrName, String attrVal) { + Objects.requireNonNull(attrName, "AtlasGlossary attribute name"); + switch(attrName) { + case "displayName": + setDisplayName(attrVal); + break; + case "shortDescription": + setShortDescription(attrVal); + break; + case "longDescription": + setLongDescription(attrVal); + break; + default: + throw new IllegalArgumentException("Invalid attribute '" + attrName + "' for object AtlasGlossaryCategory"); + } + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("AtlasGlossaryCategory{"); + sb.append("displayName='").append(getDisplayName()).append('\''); + sb.append(", shortDescription='").append(getShortDescription()).append('\''); + sb.append(", longDescription='").append(getLongDescription()).append('\''); + sb.append(", anchor=").append(anchor); + sb.append(", parentCategory=").append(parentCategory); + sb.append(", childrenCategories=").append(childrenCategories); + sb.append(", terms=").append(terms); + sb.append(", classifications=").append(getClassifications()); + sb.append('}'); + return sb.toString(); + } + + @Override + protected StringBuilder toString(final StringBuilder sb) { + return sb == null ? new StringBuilder(toString()) : sb.append(toString()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof AtlasGlossaryCategory)) return false; + if (!super.equals(o)) return false; + final AtlasGlossaryCategory category = (AtlasGlossaryCategory) o; + return Objects.equals(getDisplayName(), category.getDisplayName()) && + Objects.equals(getShortDescription(), category.getShortDescription()) && + Objects.equals(getLongDescription(), category.getLongDescription()) && + Objects.equals(anchor, category.anchor) && + Objects.equals(parentCategory, category.parentCategory) && + Objects.equals(childrenCategories, category.childrenCategories) && + Objects.equals(terms, category.terms) && + Objects.equals(getClassifications(), category.getClassifications()); + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), getDisplayName(), getShortDescription(), getLongDescription(), + anchor, parentCategory, childrenCategories, + terms, getClassifications()); + } +}
