2323import org .apache .atlas .glossary .GlossaryService ;
2424import org .apache .atlas .model .impexp .AtlasExportRequest ;
2525import org .apache .atlas .model .impexp .AtlasExportResult ;
26+ import org .apache .atlas .model .instance .AtlasClassification ;
2627import org .apache .atlas .model .instance .AtlasEntity ;
2728import org .apache .atlas .model .instance .AtlasEntity .AtlasEntityWithExtInfo ;
2829import org .apache .atlas .model .instance .AtlasObjectId ;
3435import org .apache .atlas .model .typedef .AtlasStructDef ;
3536import org .apache .atlas .model .typedef .AtlasTypesDef ;
3637import org .apache .atlas .repository .graph .GraphHelper ;
38+ import org .apache .atlas .repository .graphdb .AtlasEdge ;
39+ import org .apache .atlas .repository .graphdb .AtlasEdgeDirection ;
3740import org .apache .atlas .repository .graphdb .AtlasGraph ;
3841import org .apache .atlas .repository .graphdb .AtlasVertex ;
3942import org .apache .atlas .repository .store .graph .v2 .AtlasGraphUtilsV2 ;
4346import org .apache .atlas .util .AtlasGremlinQueryProvider ;
4447import org .apache .commons .collections .CollectionUtils ;
4548import org .apache .commons .collections .MapUtils ;
49+ import org .apache .commons .lang3 .StringUtils ;
4650import org .slf4j .Logger ;
4751import org .slf4j .LoggerFactory ;
4852import org .springframework .stereotype .Component ;
4953
5054import javax .inject .Inject ;
5155
56+ import java .util .ArrayDeque ;
5257import java .util .ArrayList ;
5358import java .util .HashMap ;
5459import java .util .HashSet ;
60+ import java .util .Iterator ;
5561import java .util .List ;
5662import java .util .Map ;
63+ import java .util .Queue ;
5764import java .util .Set ;
5865
5966import static org .apache .atlas .model .impexp .AtlasExportRequest .FETCH_TYPE_CONNECTED ;
6067import static org .apache .atlas .model .impexp .AtlasExportRequest .FETCH_TYPE_FULL ;
6168import static org .apache .atlas .model .impexp .AtlasExportRequest .FETCH_TYPE_INCREMENTAL ;
69+ import static org .apache .atlas .repository .Constants .CLASSIFICATION_EDGE_IS_PROPAGATED_PROPERTY_KEY ;
70+ import static org .apache .atlas .repository .Constants .CLASSIFICATION_EDGE_NAME_PROPERTY_KEY ;
71+ import static org .apache .atlas .repository .Constants .CLASSIFICATION_ENTITY_GUID ;
72+ import static org .apache .atlas .repository .Constants .CLASSIFICATION_LABEL ;
6273import static org .apache .atlas .repository .Constants .GUID_PROPERTY_KEY ;
6374import static org .apache .atlas .repository .Constants .MODIFICATION_TIMESTAMP_PROPERTY_KEY ;
75+ import static org .apache .atlas .repository .graph .GraphHelper .getGuid ;
76+ import static org .apache .atlas .repository .graph .GraphHelper .getTypeName ;
77+ import static org .apache .atlas .type .AtlasStructType .AtlasAttribute .AtlasRelationshipEdgeDirection .IN ;
78+ import static org .apache .atlas .type .AtlasStructType .AtlasAttribute .AtlasRelationshipEdgeDirection .OUT ;
6479
6580@ Component
6681public class ExportService {
@@ -75,6 +90,8 @@ public class ExportService {
7590 private final AuditsWriter auditsWriter ;
7691 private ExportTypeProcessor exportTypeProcessor ;
7792 private static final String ATLAS_TYPE_HIVE_DB = "hive_db" ;
93+ public static final String PROCESS_INPUTS = "__Process.inputs" ;
94+ public static final String PROCESS_OUTPUTS = "__Process.outputs" ;
7895
7996 @ Inject
8097 public ExportService (final AtlasTypeRegistry typeRegistry , AtlasGraph graph , AuditsWriter auditsWriter , HdfsPathEntityCreator hdfsPathEntityCreator , GlossaryService glossaryService ) {
@@ -91,13 +108,14 @@ public AtlasExportResult run(ZipSink exportSink, AtlasExportRequest request, Str
91108 long startTime = System .currentTimeMillis ();
92109 AtlasExportResult result = new AtlasExportResult (request , userName , requestingIP , hostName , startTime , getCurrentChangeMarker ());
93110 ExportContext context = new ExportContext (result , exportSink );
111+ RelationshipAttributesExtractor relationshipAttributesExtractor = new RelationshipAttributesExtractor (typeRegistry );
94112
95113 exportTypeProcessor = new ExportTypeProcessor (typeRegistry , glossaryService );
96114
97115 try {
98116 LOG .info ("==> export(user={}, from={})" , userName , requestingIP );
99117
100- AtlasExportResult .OperationStatus [] statuses = processItems (request , context );
118+ AtlasExportResult .OperationStatus [] statuses = processItems (request , context , relationshipAttributesExtractor );
101119
102120 processTypesDef (context );
103121
@@ -219,20 +237,20 @@ private void processTypesDef(ExportContext context) {
219237 }
220238 }
221239
222- private AtlasExportResult .OperationStatus [] processItems (AtlasExportRequest request , ExportContext context ) {
223- AtlasExportResult .OperationStatus [] statuses = new AtlasExportResult .OperationStatus [request .getItemsToExport ().size ()];
224- List <AtlasObjectId > itemsToExport = request .getItemsToExport ();
240+ private AtlasExportResult .OperationStatus [] processItems (AtlasExportRequest request , ExportContext context , RelationshipAttributesExtractor relationshipAttributesExtractor ) {
241+ AtlasExportResult .OperationStatus [] statuses = new AtlasExportResult .OperationStatus [request .getItemsToExport ().size ()];
242+ List <AtlasObjectId > itemsToExport = request .getItemsToExport ();
225243
226244 for (int i = 0 ; i < itemsToExport .size (); i ++) {
227245 AtlasObjectId item = itemsToExport .get (i );
228246
229- statuses [i ] = processObjectId (item , context );
247+ statuses [i ] = processObjectId (item , context , relationshipAttributesExtractor );
230248 }
231249
232250 return statuses ;
233251 }
234252
235- private AtlasExportResult .OperationStatus processObjectId (AtlasObjectId item , ExportContext context ) {
253+ private AtlasExportResult .OperationStatus processObjectId (AtlasObjectId item , ExportContext context , RelationshipAttributesExtractor relationshipAttributesExtractor ) {
236254 LOG .debug ("==> processObjectId({})" , item );
237255
238256 try {
@@ -266,6 +284,11 @@ private AtlasExportResult.OperationStatus processObjectId(AtlasObjectId item, Ex
266284
267285 context .isSkipConnectedFetch = false ;
268286 }
287+ if (context .fetchType != ExportFetchType .FULL && !context .skipLineage ) {
288+ for (String guid : entityGuids ) {
289+ addEntityGuids (guid , context , relationshipAttributesExtractor );
290+ }
291+ }
269292 } catch (AtlasBaseException excp ) {
270293 LOG .error ("Fetching entity failed for: {}" , item , excp );
271294
@@ -413,6 +436,91 @@ private void addEntity(AtlasEntityWithExtInfo entityWithExtInfo, ExportContext c
413436 context .reportProgress ();
414437 }
415438
439+ public void addEntityGuids (String guid , ExportContext context , RelationshipAttributesExtractor relationshipAttributesExtractor ) throws AtlasBaseException {
440+ AtlasVertex adjacentVertex ;
441+ Iterator <AtlasEdge > entityEdges ;
442+ Iterator <AtlasVertex > propagateClassificationVertices ;
443+ Iterator <AtlasVertex > appliedClassificationVertices ;
444+ String fetchedClassificationGuid ;
445+ List <AtlasClassification > processedClassifications = new ArrayList <>();
446+
447+ AtlasVertex initialEntityVertex = entityGraphRetriever .getEntityVertex (guid );
448+ for (AtlasClassification currentClassification : entityGraphRetriever .getAllClassifications (initialEntityVertex )) {
449+ if (context .guidsProcessed .contains (currentClassification .getEntityGuid ())) {
450+ processedClassifications .add (currentClassification );
451+ }
452+ }
453+ context .newAddedGuids .add (guid );
454+ while (!context .newAddedGuids .isEmpty ()) {
455+ String currentGuid = context .newAddedGuids .poll ();
456+
457+ AtlasVertex entityVertex = entityGraphRetriever .getEntityVertex (currentGuid );
458+ String entityTypeName = getTypeName (entityVertex );
459+ List <AtlasClassification > classifications = entityGraphRetriever .getAllClassifications (entityVertex );
460+ if (CollectionUtils .isNotEmpty (processedClassifications )) {
461+ classifications .removeAll (processedClassifications );
462+ }
463+ if (CollectionUtils .isNotEmpty (classifications )) {
464+ for (AtlasClassification classification : classifications ) {
465+ String classificationName = classification .getTypeName ();
466+ boolean isProcess = relationshipAttributesExtractor .isLineageType (entityTypeName );
467+ entityEdges = isProcess
468+ ? GraphHelper .getEdgesForLabel (entityVertex , PROCESS_INPUTS , OUT )
469+ : GraphHelper .getEdgesForLabel (entityVertex , PROCESS_OUTPUTS , IN );
470+ while (entityEdges .hasNext ()) {
471+ AtlasEdge propagationEdge = entityEdges .next ();
472+ AtlasVertex outVertex = propagationEdge .getOutVertex ();
473+ AtlasVertex inVertex = propagationEdge .getInVertex ();
474+ adjacentVertex = StringUtils .equals (outVertex .getIdForDisplay (), entityVertex .getIdForDisplay ()) ? inVertex : outVertex ;
475+ String adjacentGuid = getGuid (adjacentVertex );
476+ boolean isPropagated = false ;
477+ propagateClassificationVertices = getClassificationVertices (inVertex , outVertex , isProcess , true , classificationName );
478+ while (propagateClassificationVertices .hasNext ()) {
479+ AtlasVertex classificationVertex = propagateClassificationVertices .next ();
480+ fetchedClassificationGuid = classificationVertex .getProperty (CLASSIFICATION_ENTITY_GUID , String .class );
481+ if (StringUtils .equals (classification .getEntityGuid (), fetchedClassificationGuid )) {
482+ addAdjacentVertices (context , adjacentGuid );
483+ isPropagated = true ;
484+ }
485+ }
486+ if (!isPropagated ) {
487+ appliedClassificationVertices = getClassificationVertices (inVertex , outVertex , isProcess , false , classificationName );
488+
489+ while (appliedClassificationVertices .hasNext ()) {
490+ AtlasVertex classificationVertex = appliedClassificationVertices .next ();
491+ fetchedClassificationGuid = classificationVertex .getProperty (CLASSIFICATION_ENTITY_GUID , String .class );
492+ if (StringUtils .equals (classification .getEntityGuid (), fetchedClassificationGuid )) {
493+ addAdjacentVertices (context , adjacentGuid );
494+ break ;
495+ }
496+ }
497+ }
498+ }
499+ }
500+ }
501+ }
502+ }
503+
504+ private Iterator <AtlasVertex > getClassificationVertices (AtlasVertex inVertex , AtlasVertex outVertex ,
505+ boolean isProcess , boolean isPropagated , String name ) {
506+ AtlasVertex base = isProcess ? inVertex : outVertex ;
507+ return base .query ()
508+ .direction (AtlasEdgeDirection .OUT )
509+ .label (CLASSIFICATION_LABEL )
510+ .has (CLASSIFICATION_EDGE_IS_PROPAGATED_PROPERTY_KEY , isPropagated )
511+ .has (CLASSIFICATION_EDGE_NAME_PROPERTY_KEY , name )
512+ .vertices ().iterator ();
513+ }
514+
515+ private void addAdjacentVertices (ExportContext context , String adjacentGuid ) throws AtlasBaseException {
516+ if (!context .newAddedGuids .contains (adjacentGuid )) {
517+ context .newAddedGuids .add (adjacentGuid );
518+ }
519+ if (!context .sink .guids .contains (adjacentGuid )) {
520+ context .addToSink (entityGraphRetriever .toAtlasEntityWithExtInfo (adjacentGuid ));
521+ }
522+ }
523+
416524 public enum TraversalDirection {
417525 UNKNOWN ,
418526 INWARD ,
@@ -450,6 +558,7 @@ static class ExportContext {
450558 final UniqueList <String > entityCreationOrder = new UniqueList <>();
451559 final Set <String > guidsProcessed = new HashSet <>();
452560 final UniqueList <String > guidsToProcess = new UniqueList <>();
561+ final Queue <String > newAddedGuids = new ArrayDeque <>();
453562 final UniqueList <String > lineageToProcess = new UniqueList <>();
454563 final Set <String > lineageProcessed = new HashSet <>();
455564 final Map <String , TraversalDirection > guidDirection = new HashMap <>();
@@ -511,6 +620,7 @@ public void clear() {
511620 guidsToProcess .clear ();
512621 guidsProcessed .clear ();
513622 guidDirection .clear ();
623+ newAddedGuids .clear ();
514624 startingEntityType = null ;
515625 }
516626
0 commit comments