/** * */ package com.thinkbiganalytics.metadata.modeshape.feed; /*- * #%L * kylo-metadata-modeshape * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Value; import com.thinkbiganalytics.metadata.api.category.Category; import com.thinkbiganalytics.metadata.api.datasource.Datasource; import com.thinkbiganalytics.metadata.api.feed.Feed; import com.thinkbiganalytics.metadata.api.feed.FeedDestination; import com.thinkbiganalytics.metadata.api.feed.FeedPrecondition; import com.thinkbiganalytics.metadata.api.feed.FeedSource; import com.thinkbiganalytics.metadata.api.template.FeedManagerTemplate; import com.thinkbiganalytics.metadata.modeshape.MetadataRepositoryException; import com.thinkbiganalytics.metadata.modeshape.common.JcrPropertiesEntity; import com.thinkbiganalytics.metadata.modeshape.datasource.JcrDatasource; import com.thinkbiganalytics.metadata.modeshape.sla.JcrServiceLevelAgreement; import com.thinkbiganalytics.metadata.modeshape.support.JcrPropertyUtil; import com.thinkbiganalytics.metadata.modeshape.support.JcrUtil; import com.thinkbiganalytics.metadata.modeshape.support.JcrVersionUtil; import com.thinkbiganalytics.metadata.modeshape.template.JcrFeedTemplate; import com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * */ public class FeedDetails extends JcrPropertiesEntity { private static final Logger log = LoggerFactory.getLogger(FeedDetails.class); public static final String NODE_TYPE = "tba:feedDetails"; public static final String FEED_JSON = "tba:json"; public static final String PROCESS_GROUP_ID = "tba:processGroupId"; public static final String FEED_TEMPLATE = "tba:feedTemplate"; public static final String PRECONDITION = "tba:precondition"; public static final String DEPENDENTS = "tba:dependentFeeds"; public static final String USED_BY_FEEDS = "tba:usedByFeeds"; public static final String SOURCE_NAME = "tba:sources"; public static final String DESTINATION_NAME = "tba:destinations"; public static final String TEMPLATE = "tba:feedTemplate"; public static final String SLA = "tba:slas"; private FeedSummary summary; /** * @param node */ public FeedDetails(Node node, FeedSummary summary) { super(node); this.summary = summary; } protected JcrFeed getParentFeed() { return this.summary.getParentFeed(); } protected FeedSummary getParentSummary() { return this.summary; } public List<? extends FeedSource> getSources() { return JcrUtil.getJcrObjects(this.node, SOURCE_NAME, JcrFeedSource.class); } public List<? extends FeedDestination> getDestinations() { return JcrUtil.getJcrObjects(this.node, DESTINATION_NAME, JcrFeedDestination.class); } public <C extends Category> List<Feed> getDependentFeeds() { List<Feed> deps = new ArrayList<>(); Set<Node> depNodes = JcrPropertyUtil.getSetProperty(this.node, DEPENDENTS); for (Node depNode : depNodes) { deps.add(new JcrFeed(depNode, this.summary.getParentFeed().getOpsAccessProvider().orElse(null))); } return deps; } public boolean addDependentFeed(Feed feed) { JcrFeed dependent = (JcrFeed) feed; Node depNode = dependent.getNode(); feed.addUsedByFeed(getParentFeed()); return JcrPropertyUtil.addToSetProperty(this.node, DEPENDENTS, depNode, true); } public boolean removeDependentFeed(Feed feed) { JcrFeed dependent = (JcrFeed) feed; Node depNode = dependent.getNode(); feed.removeUsedByFeed(getParentFeed()); boolean weakRef = false; Optional<Property> prop = JcrPropertyUtil.findProperty(this.node, DEPENDENTS); if (prop.isPresent()) { try { weakRef = PropertyType.WEAKREFERENCE == prop.get().getType(); } catch (RepositoryException e) { log.error("Error removeDependentFeed for {}. Unable to identify if the property is a Weak Reference or not {} ", feed.getName(), e.getMessage(), e); } } return JcrPropertyUtil.removeFromSetProperty(this.node, DEPENDENTS, depNode, weakRef); } public boolean addUsedByFeed(Feed feed) { JcrFeed dependent = (JcrFeed) feed; Node depNode = dependent.getNode(); return JcrPropertyUtil.addToSetProperty(this.node, USED_BY_FEEDS, depNode, true); } public List<Feed> getUsedByFeeds() { List<Feed> deps = new ArrayList<>(); Set<Node> depNodes = JcrPropertyUtil.getSetProperty(this.node, USED_BY_FEEDS); for (Node depNode : depNodes) { deps.add(new JcrFeed(depNode, this.summary.getParentFeed().getOpsAccessProvider().orElse(null))); } return deps; } public boolean removeUsedByFeed(Feed feed) { JcrFeed dependent = (JcrFeed) feed; Node depNode = dependent.getNode(); boolean weakRef = false; Optional<Property> prop = JcrPropertyUtil.findProperty(this.node, USED_BY_FEEDS); if (prop.isPresent()) { try { weakRef = PropertyType.WEAKREFERENCE == prop.get().getType(); } catch (RepositoryException e) { log.error("Error removeUsedByFeed for {}. Unable to identify if the property is a Weak Reference or not {} ", feed.getName(), e.getMessage(), e); } } return JcrPropertyUtil.removeFromSetProperty(this.node, USED_BY_FEEDS, depNode, weakRef); } public FeedSource getSource(final Datasource.ID id) { List<? extends FeedSource> sources = getSources(); if (sources != null) { return sources.stream().filter(feedSource -> feedSource.getDatasource().getId().equals(id)).findFirst().orElse(null); } return null; } public FeedDestination getDestination(final Datasource.ID id) { List<? extends FeedDestination> destinations = getDestinations(); if (destinations != null) { return destinations.stream().filter(feedDestination -> feedDestination.getDatasource().getId().equals(id)).findFirst().orElse(null); } return null; } public FeedPrecondition getPrecondition() { try { if (this.node.hasNode(PRECONDITION)) { return new JcrFeedPrecondition(this.node.getNode(PRECONDITION), getParentFeed()); } else { return null; } } catch (RepositoryException e) { throw new MetadataRepositoryException("Failed to retrieve the feed precondition", e); } } public FeedManagerTemplate getTemplate() { return getProperty(TEMPLATE, JcrFeedTemplate.class); } public void setTemplate(FeedManagerTemplate template) { setProperty(TEMPLATE, template); template.addFeed(getParentFeed()); } public List<ServiceLevelAgreement> getServiceLevelAgreements() { Set<Node> list = JcrPropertyUtil.getReferencedNodeSet(this.node, SLA); List<ServiceLevelAgreement> serviceLevelAgreements = new ArrayList<>(); if (list != null) { for (Node n : list) { serviceLevelAgreements.add(JcrUtil.createJcrObject(n, JcrServiceLevelAgreement.class)); } } return serviceLevelAgreements; } public void setServiceLevelAgreements(List<? extends ServiceLevelAgreement> serviceLevelAgreements) { setProperty(SLA, serviceLevelAgreements); } public void removeServiceLevelAgreement(ServiceLevelAgreement.ID id) { try { Set<Node> nodes = JcrPropertyUtil.getSetProperty(this.node, SLA); Set<Value> updatedSet = new HashSet<>(); for (Node node : nodes) { if (!node.getIdentifier().equalsIgnoreCase(id.toString())) { Value value = this.node.getSession().getValueFactory().createValue(node, true); updatedSet.add(value); } } node.setProperty(SLA, (Value[]) updatedSet.stream().toArray(size -> new Value[size])); } catch (RepositoryException e) { throw new MetadataRepositoryException("Unable to remove reference to SLA " + id + "from feed " + this.getId()); } } public boolean addServiceLevelAgreement(ServiceLevelAgreement sla) { JcrServiceLevelAgreement jcrServiceLevelAgreement = (JcrServiceLevelAgreement) sla; Node node = jcrServiceLevelAgreement.getNode(); //add a ref to this node return JcrPropertyUtil.addToSetProperty(this.node, SLA, node, true); } public String getJson() { return getProperty(FeedDetails.FEED_JSON, String.class); } public void setJson(String json) { setProperty(FeedDetails.FEED_JSON, json); } public String getNifiProcessGroupId() { return getProperty(FeedDetails.PROCESS_GROUP_ID, String.class); } public void setNifiProcessGroupId(String id) { setProperty(FeedDetails.PROCESS_GROUP_ID, id); } protected JcrFeedSource ensureFeedSource(JcrDatasource datasource) { Node feedSrcNode = JcrUtil.addNode(getNode(), FeedDetails.SOURCE_NAME, JcrFeedSource.NODE_TYPE); return new JcrFeedSource(feedSrcNode, datasource); } protected JcrFeedDestination ensureFeedDestination(JcrDatasource datasource) { Node feedDestNode = JcrUtil.addNode(getNode(), FeedDetails.DESTINATION_NAME, JcrFeedDestination.NODE_TYPE); return new JcrFeedDestination(feedDestNode, datasource); } protected void removeFeedSource(JcrFeedSource source) { try { JcrVersionUtil.checkout(source.getNode().getParent()); source.getNode().remove(); } catch (RepositoryException e) { throw new MetadataRepositoryException("nable to remove feed source for feed " + getParentSummary().getSystemName(), e); } } protected void removeFeedDestination(JcrFeedDestination dest) { try { JcrVersionUtil.checkout(dest.getNode().getParent()); dest.getNode().remove(); } catch (RepositoryException e) { throw new MetadataRepositoryException("nable to remove feed destination for feed " + getParentSummary().getSystemName(), e); } } protected void removeFeedSources() { try { List<? extends FeedSource> sources = getSources(); if (sources != null && !sources.isEmpty()) { //checkout the feed JcrVersionUtil.checkout(getParentSummary().getNode()); sources.stream().forEach(source -> { try { Node sourceNode = ((JcrFeedSource) source).getNode(); ((JcrDatasource) ((JcrFeedSource) source).getDatasource()).removeSourceNode(sourceNode); sourceNode.remove(); } catch (RepositoryException e) { e.printStackTrace(); } }); } } catch (RepositoryException e) { throw new MetadataRepositoryException("nable to remove feed sources for feed " + getParentSummary().getSystemName(), e); } } protected void removeFeedDestinations() { try { List<? extends FeedDestination> destinations = getDestinations(); if (destinations != null && !destinations.isEmpty()) { JcrVersionUtil.checkout(getParentSummary().getNode()); destinations.stream().forEach(dest -> { try { Node destNode = ((JcrFeedDestination) dest).getNode(); ((JcrDatasource) ((JcrFeedDestination) dest).getDatasource()).removeDestinationNode(destNode); destNode.remove(); ((JcrFeedDestination) dest).getNode().remove(); } catch (RepositoryException e) { e.printStackTrace(); } }); } } catch (RepositoryException e) { throw new MetadataRepositoryException("unable to remove feed destinations for feed " + getParentSummary().getSystemName(), e); } } protected Node createNewPrecondition() { try { Node feedNode = getNode(); Node precondNode = JcrUtil.getOrCreateNode(feedNode, FeedDetails.PRECONDITION, JcrFeed.PRECONDITION_TYPE, true); if (precondNode.hasProperty(JcrFeedPrecondition.SLA_REF)) { precondNode.getProperty(JcrFeedPrecondition.SLA_REF).remove(); } if (precondNode.hasNode(JcrFeedPrecondition.SLA)) { precondNode.getNode(JcrFeedPrecondition.SLA).remove(); } return precondNode.addNode(JcrFeedPrecondition.SLA, JcrFeedPrecondition.SLA_TYPE); } catch (RepositoryException e) { throw new MetadataRepositoryException("Failed to create the precondition for feed " + getParentFeed().getId(), e); } } }