private void addOrUpdate()

in security-admin/src/main/java/org/apache/ranger/rest/ServiceTagsProcessor.java [83:409]


    private void addOrUpdate(ServiceTags serviceTags) throws Exception {
        LOG.debug("==> ServiceTagsProcessor.createOrUpdate()");

        RangerPerfTracer perfTotal = null;
        RangerPerfTracer perf      = null;

        Map<Long, RangerTagDef>          tagDefsInStore   = new HashMap<>();
        Map<Long, RangerServiceResource> resourcesInStore = new HashMap<>();

        if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
            perfTotal = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.addOrUpdate()");
        }

        if (MapUtils.isNotEmpty(serviceTags.getTagDefinitions())) {
            RangerTagDef tagDef = null;

            try {
                for (Map.Entry<Long, RangerTagDef> entry : serviceTags.getTagDefinitions().entrySet()) {
                    tagDef = entry.getValue();

                    RangerTagDef existing = null;

                    if (StringUtils.isNotEmpty(tagDef.getGuid())) {
                        existing = tagStore.getTagDefByGuid(tagDef.getGuid());
                    }

                    if (existing == null && StringUtils.isNotEmpty(tagDef.getName())) {
                        existing = tagStore.getTagDefByName(tagDef.getName());
                    }

                    RangerTagDef tagDefInStore;

                    if (existing == null) {
                        tagDefInStore = tagStore.createTagDef(tagDef);
                    } else {
                        LOG.debug("tagDef for name: {} exists, will not update it", tagDef.getName());

                        tagDefInStore = existing;
                    }

                    tagDefsInStore.put(entry.getKey(), tagDefInStore);
                }
            } catch (Exception exception) {
                LOG.error("createTagDef failed, tagDef={}", tagDef, exception);

                throw exception;
            }
        }

        List<RangerServiceResource> resources = serviceTags.getServiceResources();

        if (CollectionUtils.isNotEmpty(resources)) {
            RangerServiceResource resource = null;

            try {
                for (RangerServiceResource rangerServiceResource : resources) {
                    resource = rangerServiceResource;

                    if (StringUtils.isBlank(resource.getServiceName())) {
                        resource.setServiceName(serviceTags.getServiceName());
                    }

                    RangerServiceResource existing   = null;
                    Long                  resourceId = resource.getId();

                    if (StringUtils.isNotEmpty(resource.getGuid())) {
                        if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                            perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.search_service_resource_by_guid(" + resourceId + ")");
                        }

                        existing = tagStore.getServiceResourceByGuid(resource.getGuid());

                        RangerPerfTracer.logAlways(perf);
                    }

                    if (existing == null) {
                        if (MapUtils.isNotEmpty(resource.getResourceElements())) {
                            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                                perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.search_service_resource_by_signature(" + resourceId + ")");
                            }

                            RangerServiceResourceSignature serializer        = new RangerServiceResourceSignature(resource);
                            String                         resourceSignature = serializer.getSignature();

                            resource.setResourceSignature(resourceSignature);

                            existing = tagStore.getServiceResourceByServiceAndResourceSignature(resource.getServiceName(), resourceSignature);

                            RangerPerfTracer.logAlways(perf);
                        }
                    }

                    if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                        perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.createOrUpdate_service_resource(" + resourceId + ")");
                    }

                    RangerServiceResource resourceInStore;

                    if (existing == null) {
                        resourceInStore = tagStore.createServiceResource(resource);
                    } else if (StringUtils.isEmpty(resource.getServiceName()) || MapUtils.isEmpty(resource.getResourceElements())) {
                        resourceInStore = existing;
                    } else {
                        resource.setId(existing.getId());
                        resource.setGuid(existing.getGuid());

                        resourceInStore = tagStore.updateServiceResource(resource);
                    }

                    resourcesInStore.put(resourceId, resourceInStore);

                    RangerPerfTracer.logAlways(perf);
                }
            } catch (Exception exception) {
                LOG.error("createServiceResource failed, resource={}", resource, exception);

                throw exception;
            }
        }

        if (MapUtils.isNotEmpty(serviceTags.getResourceToTagIds())) {
            for (Map.Entry<Long, List<Long>> entry : serviceTags.getResourceToTagIds().entrySet()) {
                Long                  resourceId      = entry.getKey();
                RangerServiceResource resourceInStore = resourcesInStore.get(resourceId);

                if (resourceInStore == null) {
                    LOG.error("Resource (id={}) not found. Skipping tags update", resourceId);
                    continue;
                }

                if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                    perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.get_tags_for_service_resource(" + resourceInStore.getId() + ")");
                }

                // Get all tags associated with this resourceId
                List<RangerTag> associatedTags;

                try {
                    associatedTags = tagStore.getTagsForResourceId(resourceInStore.getId());
                } catch (Exception exception) {
                    LOG.error("RangerTags cannot be retrieved for resource with guid={}", resourceInStore.getGuid());

                    throw exception;
                } finally {
                    RangerPerfTracer.logAlways(perf);
                }

                List<RangerTag> tagsToRetain    = new ArrayList<>();
                boolean         isAnyTagUpdated = false;
                List<Long>      tagIds          = entry.getValue();

                try {
                    for (Long tagId : tagIds) {
                        RangerTag incomingTag = MapUtils.isNotEmpty(serviceTags.getTags()) ? serviceTags.getTags().get(tagId) : null;

                        if (incomingTag == null) {
                            LOG.error("Tag (id={}) not found. Skipping addition of this tag for resource (id={})", tagId, resourceId);
                            continue;
                        }

                        RangerTag matchingTag = findMatchingTag(incomingTag, associatedTags);

                        if (matchingTag == null) {
                            LOG.debug("Did not find matching tag for tagId={}", tagId);

                            // create new tag from incoming tag and associate it with service-resource
                            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                                perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.create_tag(" + tagId + ")");
                            }

                            RangerTag newTag = tagStore.createTag(incomingTag);

                            RangerPerfTracer.logAlways(perf);

                            RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();

                            tagResourceMap.setTagId(newTag.getId());
                            tagResourceMap.setResourceId(resourceInStore.getId());

                            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                                perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.create_tagResourceMap(" + tagId + ")");
                            }

                            tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);

                            RangerPerfTracer.logAlways(perf);

                            associatedTags.add(newTag);
                            tagsToRetain.add(newTag);
                        } else {
                            LOG.debug("Found matching tag for tagId={}, matchingTag={}", tagId, matchingTag);

                            if (isResourcePrivateTag(incomingTag)) {
                                if (!isResourcePrivateTag(matchingTag)) {
                                    // create new tag from incoming tag and associate it with service-resource
                                    RangerTag newTag = tagStore.createTag(incomingTag);

                                    RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();

                                    tagResourceMap.setTagId(newTag.getId());
                                    tagResourceMap.setResourceId(resourceInStore.getId());

                                    tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);

                                    associatedTags.add(newTag);
                                    tagsToRetain.add(newTag);
                                } else {
                                    tagsToRetain.add(matchingTag);

                                    boolean isTagUpdateNeeded = false;

                                    // Note that as there is no easy way to check validityPeriods for equality, an easy way to rule out the possibility of validityPeriods
                                    // not matching is to check if both old and new tags have empty validityPeriods
                                    if (matchingTag.getGuid() != null && matchingTag.getGuid().equals(incomingTag.getGuid())) {
                                        if (isMatch(incomingTag, matchingTag) && CollectionUtils.isEmpty(incomingTag.getValidityPeriods()) && CollectionUtils.isEmpty(matchingTag.getValidityPeriods())) {
                                            LOG.debug("No need to update existing-tag:[{}] with incoming-tag:[{}]", matchingTag, incomingTag);
                                        } else {
                                            isTagUpdateNeeded = true;
                                        }
                                    } else {
                                        if (CollectionUtils.isEmpty(incomingTag.getValidityPeriods()) && CollectionUtils.isEmpty(matchingTag.getValidityPeriods())) {
                                            // Completely matched tags. No need to update
                                            LOG.debug("No need to update existing-tag:[{}] with incoming-tag:[{}]", matchingTag, incomingTag);
                                        } else {
                                            isTagUpdateNeeded = true;
                                        }
                                    }
                                    if (isTagUpdateNeeded) {
                                        // Keep this tag, and update it with attribute-values and validity schedules from incoming tag
                                        LOG.debug("Updating existing private tag with id={}", matchingTag.getId());

                                        incomingTag.setId(matchingTag.getId());

                                        tagStore.updateTag(incomingTag);

                                        isAnyTagUpdated = true;
                                    }
                                }
                            } else { // shared model
                                if (isResourcePrivateTag(matchingTag)) {
                                    // create new tag from incoming tag and associate it with service-resource
                                    RangerTag newTag = tagStore.createTag(incomingTag);

                                    RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();

                                    tagResourceMap.setTagId(newTag.getId());
                                    tagResourceMap.setResourceId(resourceInStore.getId());

                                    tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);

                                    associatedTags.add(newTag);
                                    tagsToRetain.add(newTag);
                                } else {
                                    // Keep this tag, but update it with attribute-values from incoming tag
                                    tagsToRetain.add(matchingTag);

                                    // Update shared tag with new values
                                    incomingTag.setId(matchingTag.getId());

                                    tagStore.updateTag(incomingTag);

                                    // associate with service-resource if not already associated
                                    if (findTagInList(matchingTag, associatedTags) == null) {
                                        RangerTagResourceMap tagResourceMap = new RangerTagResourceMap();

                                        tagResourceMap.setTagId(matchingTag.getId());
                                        tagResourceMap.setResourceId(resourceInStore.getId());

                                        tagResourceMap = tagStore.createTagResourceMap(tagResourceMap);
                                    } else {
                                        isAnyTagUpdated = true;
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception exception) {
                    LOG.error("createRangerTagResourceMap failed", exception);

                    throw exception;
                }

                if (CollectionUtils.isNotEmpty(associatedTags)) {
                    Long tagId = null;

                    try {
                        for (RangerTag associatedTag : associatedTags) {
                            if (findTagInList(associatedTag, tagsToRetain) == null) {
                                tagId = associatedTag.getId();

                                RangerTagResourceMap tagResourceMap = tagStore.getTagResourceMapForTagAndResourceId(tagId, resourceInStore.getId());

                                if (tagResourceMap != null) {
                                    tagStore.deleteTagResourceMap(tagResourceMap.getId());
                                }

                                LOG.debug("Deleted tagResourceMap(tagId={}, resourceId={}", tagId, resourceInStore.getId());
                            }
                        }
                    } catch (Exception exception) {
                        LOG.error("deleteTagResourceMap failed, tagId={}, resourceId={}", tagId, resourceInStore.getId());

                        throw exception;
                    }
                }

                if (isAnyTagUpdated) {
                    if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG_ADD_OR_UPDATE)) {
                        perf = RangerPerfTracer.getPerfTracer(PERF_LOG_ADD_OR_UPDATE, "tags.refreshServiceResource(" + resourceInStore.getId() + ")");
                    }

                    tagStore.refreshServiceResource(resourceInStore.getId());

                    RangerPerfTracer.logAlways(perf);
                } else {
                    if (CollectionUtils.isEmpty(tagIds)) {
                        // No tags associated with the resource - delete the resource too
                        tagStore.deleteServiceResource(resourceInStore.getId());
                    }
                }
            }
        }

        RangerPerfTracer.logAlways(perfTotal);

        LOG.debug("<== ServiceTagsProcessor.createOrUpdate()");
    }