package com.thinkbiganalytics.metadata.modeshape.feed;
/*-
* #%L
* thinkbig-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 com.google.common.base.Predicate;
import com.thinkbiganalytics.metadata.api.MetadataAccess;
import com.thinkbiganalytics.metadata.api.category.Category;
import com.thinkbiganalytics.metadata.api.category.CategoryNotFoundException;
import com.thinkbiganalytics.metadata.api.category.CategoryProvider;
import com.thinkbiganalytics.metadata.api.category.security.CategoryAccessControl;
import com.thinkbiganalytics.metadata.api.datasource.Datasource;
import com.thinkbiganalytics.metadata.api.datasource.DatasourceNotFoundException;
import com.thinkbiganalytics.metadata.api.datasource.DatasourceProvider;
import com.thinkbiganalytics.metadata.api.event.MetadataChange.ChangeType;
import com.thinkbiganalytics.metadata.api.event.MetadataEventService;
import com.thinkbiganalytics.metadata.api.event.feed.FeedChange;
import com.thinkbiganalytics.metadata.api.event.feed.FeedChangeEvent;
import com.thinkbiganalytics.metadata.api.event.feed.FeedPropertyChangeEvent;
import com.thinkbiganalytics.metadata.api.event.feed.PropertyChange;
import com.thinkbiganalytics.metadata.api.extension.ExtensibleTypeProvider;
import com.thinkbiganalytics.metadata.api.extension.UserFieldDescriptor;
import com.thinkbiganalytics.metadata.api.feed.Feed;
import com.thinkbiganalytics.metadata.api.feed.Feed.ID;
import com.thinkbiganalytics.metadata.api.feed.FeedCriteria;
import com.thinkbiganalytics.metadata.api.feed.FeedDestination;
import com.thinkbiganalytics.metadata.api.feed.FeedNotFoundExcepton;
import com.thinkbiganalytics.metadata.api.feed.FeedProvider;
import com.thinkbiganalytics.metadata.api.feed.FeedSource;
import com.thinkbiganalytics.metadata.api.feed.PreconditionBuilder;
import com.thinkbiganalytics.metadata.api.feed.security.FeedAccessControl;
import com.thinkbiganalytics.metadata.api.feed.security.FeedOpsAccessControlProvider;
import com.thinkbiganalytics.metadata.api.security.HadoopSecurityGroup;
import com.thinkbiganalytics.metadata.api.template.FeedManagerTemplate;
import com.thinkbiganalytics.metadata.modeshape.AbstractMetadataCriteria;
import com.thinkbiganalytics.metadata.modeshape.BaseJcrProvider;
import com.thinkbiganalytics.metadata.modeshape.JcrMetadataAccess;
import com.thinkbiganalytics.metadata.modeshape.MetadataRepositoryException;
import com.thinkbiganalytics.metadata.modeshape.category.JcrCategory;
import com.thinkbiganalytics.metadata.modeshape.common.EntityUtil;
import com.thinkbiganalytics.metadata.modeshape.common.JcrEntity;
import com.thinkbiganalytics.metadata.modeshape.common.JcrObject;
import com.thinkbiganalytics.metadata.modeshape.datasource.JcrDatasource;
import com.thinkbiganalytics.metadata.modeshape.extension.ExtensionsConstants;
import com.thinkbiganalytics.metadata.modeshape.security.action.JcrAllowedActions;
import com.thinkbiganalytics.metadata.modeshape.security.action.JcrAllowedEntityActionsProvider;
import com.thinkbiganalytics.metadata.modeshape.sla.JcrServiceLevelAgreement;
import com.thinkbiganalytics.metadata.modeshape.sla.JcrServiceLevelAgreementProvider;
import com.thinkbiganalytics.metadata.modeshape.support.JcrPropertyUtil;
import com.thinkbiganalytics.metadata.modeshape.support.JcrQueryUtil;
import com.thinkbiganalytics.metadata.modeshape.support.JcrUtil;
import com.thinkbiganalytics.metadata.sla.api.Metric;
import com.thinkbiganalytics.metadata.sla.api.Obligation;
import com.thinkbiganalytics.metadata.sla.api.ObligationGroup.Condition;
import com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreement;
import com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreementActionConfiguration;
import com.thinkbiganalytics.metadata.sla.spi.ObligationBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ObligationGroupBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ServiceLevelAgreementBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ServiceLevelAgreementProvider;
import com.thinkbiganalytics.security.AccessController;
import com.thinkbiganalytics.security.action.AllowedActions;
import com.thinkbiganalytics.security.role.SecurityRole;
import com.thinkbiganalytics.security.role.SecurityRoleProvider;
import com.thinkbiganalytics.support.FeedNameUtil;
import org.joda.time.DateTime;
import org.springframework.security.core.context.SecurityContextHolder;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.QueryResult;
/**
* A JCR provider for {@link Feed} objects.
*/
public class JcrFeedProvider extends BaseJcrProvider<Feed, Feed.ID> implements FeedProvider {
@Inject
private CategoryProvider categoryProvider;
@Inject
private ServiceLevelAgreementProvider slaProvider;
@Inject
private DatasourceProvider datasourceProvider;
/**
* JCR node type manager
*/
@Inject
private ExtensibleTypeProvider extensibleTypeProvider;
/**
* Transaction support
*/
@Inject
private MetadataAccess metadataAccess;
@Inject
private SecurityRoleProvider roleProvider;
@Inject
private JcrAllowedEntityActionsProvider actionsProvider;
@Inject
private AccessController accessController;
@Inject
private FeedOpsAccessControlProvider opsAccessProvider;
@Inject
private MetadataEventService metadataEventService;
@Override
public String getNodeType(Class<? extends JcrEntity> jcrEntityType) {
return JcrFeed.NODE_TYPE;
}
@Override
public Class<JcrFeed> getEntityClass() {
return JcrFeed.class;
}
@Override
public Class<? extends JcrEntity> getJcrEntityClass() {
return JcrFeed.class;
}
/* (non-Javadoc)
* @see com.thinkbiganalytics.metadata.modeshape.BaseJcrProvider#create(java.lang.Object)
*/
@Override
public Feed create(Feed t) {
JcrFeed feed = (JcrFeed) super.create(t);
feed.setOpsAccessProvider(this.opsAccessProvider);
return feed;
}
@Override
public List<Feed> findAll() {
List<Feed> feeds = super.findAll();
return feeds.stream()
.map(JcrFeed.class::cast)
.map(feed -> {
feed.setOpsAccessProvider(opsAccessProvider);
return feed;
})
.collect(Collectors.toList());
}
@Override
public Feed findById(ID id) {
final JcrFeed feed = (JcrFeed) super.findById(id);
if (feed != null) {
feed.setOpsAccessProvider(this.opsAccessProvider);
}
return feed;
}
@Override
public Feed update(Feed feed) {
// feed.getCategory().getAllowedActions().checkPermission(CategoryAccessControl.CREATE_FEED);
return super.update(feed);
}
public void removeFeedSources(Feed.ID feedId) {
JcrFeed feed = (JcrFeed) findById(feedId);
feed.removeFeedSources();
}
public void removeFeedSource(Feed.ID feedId, Datasource.ID dsId) {
JcrFeed feed = (JcrFeed) findById(feedId);
JcrFeedSource source = (JcrFeedSource) feed.getSource(dsId);
if (source != null) {
feed.removeFeedSource(source);
}
}
public void removeFeedDestination(Feed.ID feedId, Datasource.ID dsId) {
JcrFeed feed = (JcrFeed) findById(feedId);
JcrFeedDestination dest = (JcrFeedDestination) feed.getDestination(dsId);
if (dest != null) {
feed.removeFeedDestination(dest);
}
}
public void removeFeedDestinations(Feed.ID feedId) {
JcrFeed feed = (JcrFeed) findById(feedId);
feed.removeFeedDestinations();
}
@Override
public FeedSource ensureFeedSource(Feed.ID feedId, Datasource.ID dsId) {
JcrFeed feed = (JcrFeed) findById(feedId);
FeedSource source = feed.getSource(dsId);
if (source == null) {
JcrDatasource datasource = (JcrDatasource) datasourceProvider.getDatasource(dsId);
if (datasource != null) {
JcrFeedSource jcrSrc = feed.ensureFeedSource(datasource);
save();
return jcrSrc;
} else {
throw new DatasourceNotFoundException(dsId);
}
} else {
return source;
}
}
@Override
public FeedSource ensureFeedSource(Feed.ID feedId, com.thinkbiganalytics.metadata.api.datasource.Datasource.ID id, com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreement.ID slaId) {
// TODO Auto-generated method stub
return null;
}
@Override
public FeedDestination ensureFeedDestination(Feed.ID feedId, com.thinkbiganalytics.metadata.api.datasource.Datasource.ID dsId) {
JcrFeed feed = (JcrFeed) findById(feedId);
FeedDestination source = feed.getDestination(dsId);
if (source == null) {
JcrDatasource datasource = (JcrDatasource) datasourceProvider.getDatasource(dsId);
if (datasource != null) {
JcrFeedDestination jcrDest = feed.ensureFeedDestination(datasource);
save();
return jcrDest;
} else {
throw new DatasourceNotFoundException(dsId);
}
} else {
return source;
}
}
@Override
public Feed ensureFeed(Category.ID categoryId, String feedSystemName) {
Category category = categoryProvider.findById(categoryId);
return ensureFeed(category.getName(), feedSystemName);
}
/**
* Ensure the Feed, but the Category must exist!
*/
@Override
public Feed ensureFeed(String categorySystemName, String feedSystemName) {
JcrCategory category = null;
try {
String categoryPath = EntityUtil.pathForCategory(categorySystemName);
Node categoryNode = getSession().getNode(categoryPath);
if (categoryNode != null) {
category = JcrUtil.createJcrObject(categoryNode, JcrCategory.class);
} else {
category = (JcrCategory) categoryProvider.findBySystemName(categorySystemName);
}
} catch (RepositoryException e) {
throw new CategoryNotFoundException("Unable to find Category for " + categorySystemName, null);
}
String feedParentPath = category.getFeedParentPath();
boolean newFeed = !hasEntityNode(feedParentPath, feedSystemName);
Node feedNode = findOrCreateEntityNode(feedParentPath, feedSystemName, getJcrEntityClass());
boolean versionable = JcrUtil.isVersionable(feedNode);
JcrFeed feed = new JcrFeed(feedNode, category, this.opsAccessProvider);
feed.setSystemName(feedSystemName);
if (newFeed) {
if (this.accessController.isEntityAccessControlled()) {
List<SecurityRole> roles = this.roleProvider.getEntityRoles(SecurityRole.FEED);
this.actionsProvider.getAvailableActions(AllowedActions.FEED)
.ifPresent(actions -> feed.enableAccessControl((JcrAllowedActions) actions, JcrMetadataAccess.getActiveUser(), roles));
} else {
this.actionsProvider.getAvailableActions(AllowedActions.FEED)
.ifPresent(actions -> feed.disableAccessControl((JcrAllowedActions) actions, JcrMetadataAccess.getActiveUser()));
}
addPostFeedChangeAction(feed, ChangeType.CREATE);
}
return feed;
}
/**
* Registers an action that produces a feed change event upon a successful transaction commit.
*
* @param feed the feed to being created
*/
private void addPostFeedChangeAction(Feed feed, ChangeType changeType) {
Feed.State state = feed.getState();
Feed.ID id = feed.getId();
String desc = feed.getQualifiedName();
final Principal principal = SecurityContextHolder.getContext().getAuthentication();
Consumer<Boolean> action = (success) -> {
if (success) {
FeedChange change = new FeedChange(changeType, desc, id, state);
FeedChangeEvent event = new FeedChangeEvent(change, DateTime.now(), principal);
metadataEventService.notify(event);
}
};
JcrMetadataAccess.addPostTransactionAction(action);
}
@Override
public Feed ensureFeed(String categorySystemName, String feedSystemName, String descr) {
Feed feed = ensureFeed(categorySystemName, feedSystemName);
feed.setDescription(descr);
return feed;
}
@Override
public Feed ensureFeed(String categorySystemName, String feedSystemName, String descr, Datasource.ID destId) {
Feed feed = ensureFeed(categorySystemName, feedSystemName, descr);
//TODO add/find datasources
return feed;
}
@Override
public Feed ensureFeed(String categorySystemName, String feedSystemName, String descr, Datasource.ID srcId, Datasource.ID destId) {
Feed feed = ensureFeed(categorySystemName, feedSystemName, descr);
if (srcId != null) {
ensureFeedSource(feed.getId(), srcId);
}
return feed;
}
@Override
public Feed createPrecondition(Feed.ID feedId, String descr, List<Metric> metrics) {
JcrFeed feed = (JcrFeed) findById(feedId);
ServiceLevelAgreementBuilder slaBldr = buildPrecondition(feed)
.name("Precondition for feed " + feedId)
.description(descr);
slaBldr.obligationGroupBuilder(Condition.REQUIRED)
.obligationBuilder()
.metric(metrics)
.build()
.build();
return feed;
}
@Override
public PreconditionBuilder buildPrecondition(ID feedId) {
JcrFeed feed = (JcrFeed) findById(feedId);
return buildPrecondition(feed);
}
private PreconditionBuilder buildPrecondition(JcrFeed feed) {
try {
if (feed != null) {
Node slaNode = feed.createNewPrecondition();
ServiceLevelAgreementBuilder slaBldr = ((JcrServiceLevelAgreementProvider) this.slaProvider).builder(slaNode);
return new JcrPreconditionbuilder(slaBldr, feed);
} else {
throw new FeedNotFoundExcepton(feed.getId());
}
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to create the precondition for feed " + feed.getId(), e);
}
}
@Override
public Feed addDependent(ID targetId, ID dependentId) {
JcrFeed target = (JcrFeed) getFeed(targetId);
if (target == null) {
throw new FeedNotFoundExcepton("The target feed to be assigned the dependent does not exists", targetId);
}
JcrFeed dependent = (JcrFeed) getFeed(dependentId);
if (dependent == null) {
throw new FeedNotFoundExcepton("The dependent feed does not exists", dependentId);
}
target.addDependentFeed(dependent);
return target;
}
@Override
public Feed removeDependent(ID feedId, ID dependentId) {
JcrFeed target = (JcrFeed) getFeed(feedId);
if (target == null) {
throw new FeedNotFoundExcepton("The target feed to be assigned the dependent does not exists", feedId);
}
JcrFeed dependent = (JcrFeed) getFeed(dependentId);
if (dependent == null) {
throw new FeedNotFoundExcepton("The dependent feed does not exists", dependentId);
}
target.removeDependentFeed(dependent);
return target;
}
@Override
public FeedCriteria feedCriteria() {
return new Criteria();
}
@Override
public Feed getFeed(Feed.ID id) {
return findById(id);
}
@Override
public List<Feed> getFeeds() {
return findAll();
}
@Override
public List<Feed> getFeeds(FeedCriteria criteria) {
if (criteria != null) {
Criteria criteriaImpl = (Criteria) criteria;
return criteriaImpl.select(getSession(), JcrFeed.NODE_TYPE, Feed.class, JcrFeed.class);
}
return null;
}
@Override
public Feed findBySystemName(String systemName) {
String categorySystemName = FeedNameUtil.category(systemName);
String feedSystemName = FeedNameUtil.feed(systemName);
return findBySystemName(categorySystemName, feedSystemName);
}
@Override
public Feed findBySystemName(String categorySystemName, String systemName) {
FeedCriteria c = feedCriteria();
if (categorySystemName != null) {
c.category(categorySystemName);
}
c.name(systemName);
List<Feed> feeds = getFeeds(c);
if (feeds != null && !feeds.isEmpty()) {
return feeds.get(0);
}
return null;
}
@Override
public List<? extends Feed> findByTemplateId(FeedManagerTemplate.ID templateId) {
String query = "SELECT * from " + EntityUtil.asQueryProperty(JcrFeed.NODE_TYPE) + " as e WHERE e." + EntityUtil.asQueryProperty(FeedDetails.TEMPLATE) + " = $id";
Map<String, String> bindParams = new HashMap<>();
bindParams.put("id", templateId.toString());
return JcrQueryUtil.find(getSession(), query, JcrFeed.class);
}
@Override
public List<? extends Feed> findByCategoryId(Category.ID categoryId) {
String query = "SELECT e.* from " + EntityUtil.asQueryProperty(JcrFeed.NODE_TYPE) + " as e "
+ "INNER JOIN ['tba:feedSummary'] as summary on ISCHILDNODE(summary,e)"
+ "WHERE summary." + EntityUtil.asQueryProperty(FeedSummary.CATEGORY) + " = $id";
Map<String, String> bindParams = new HashMap<>();
bindParams.put("id", categoryId.toString());
try {
QueryResult result = JcrQueryUtil.query(getSession(), query, bindParams);
return JcrQueryUtil.queryResultToList(result, JcrFeed.class);
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to getFeeds for Category ", e);
}
}
//
// @Override
// public FeedSource getFeedSource(com.thinkbiganalytics.metadata.api.feed.FeedSource.ID id) {
// try {
// Node node = getSession().getNodeByIdentifier(id.toString());
//
// if (node != null) {
// return JcrUtil.createJcrObject(node, JcrFeedSource.class);
// }
// } catch (RepositoryException e) {
// throw new MetadataRepositoryException("Unable to get Feed Destination for " + id);
// }
// return null;
// }
//
// @Override
// public FeedDestination getFeedDestination(com.thinkbiganalytics.metadata.api.feed.FeedDestination.ID id) {
// try {
// Node node = getSession().getNodeByIdentifier(id.toString());
//
// if (node != null) {
// return JcrUtil.createJcrObject(node, JcrFeedDestination.class);
// }
// } catch (RepositoryException e) {
// throw new MetadataRepositoryException("Unable to get Feed Destination for " + id);
// }
// return null;
//
// }
@Override
public Feed.ID resolveFeed(Serializable fid) {
return resolveId(fid);
}
//
// @Override
// public com.thinkbiganalytics.metadata.api.feed.FeedSource.ID resolveSource(Serializable sid) {
// return new JcrFeedSource.FeedSourceId((sid));
// }
//
// @Override
// public com.thinkbiganalytics.metadata.api.feed.FeedDestination.ID resolveDestination(Serializable sid) {
// return new JcrFeedDestination.FeedDestinationId(sid);
// }
@Override
public boolean enableFeed(Feed.ID id) {
Feed feed = getFeed(id);
feed.getAllowedActions().checkPermission(FeedAccessControl.ENABLE_DISABLE);
if (!feed.getState().equals(Feed.State.ENABLED)) {
feed.setState(Feed.State.ENABLED);
//Enable any SLAs on this feed
List<ServiceLevelAgreement> serviceLevelAgreements = feed.getServiceLevelAgreements();
if (serviceLevelAgreements != null) {
for (ServiceLevelAgreement sla : serviceLevelAgreements) {
JcrServiceLevelAgreement jcrSla = (JcrServiceLevelAgreement) sla;
jcrSla.enable();
}
}
return true;
}
return false;
}
@Override
public boolean disableFeed(Feed.ID id) {
Feed feed = getFeed(id);
feed.getAllowedActions().checkPermission(FeedAccessControl.ENABLE_DISABLE);
if (!feed.getState().equals(Feed.State.DISABLED)) {
feed.setState(Feed.State.DISABLED);
//disable any SLAs on this feed
List<ServiceLevelAgreement> serviceLevelAgreements = feed.getServiceLevelAgreements();
if (serviceLevelAgreements != null) {
for (ServiceLevelAgreement sla : serviceLevelAgreements) {
JcrServiceLevelAgreement jcrSla = (JcrServiceLevelAgreement) sla;
jcrSla.disabled();
}
}
return true;
}
return false;
}
@Override
public void deleteFeed(ID feedId) {
JcrFeed feed = (JcrFeed) getFeed(feedId);
if (feed != null) {
delete(feed);
}
}
@Override
public void delete(Feed feed) {
feed.getAllowedActions().checkPermission(FeedAccessControl.DELETE);
addPostFeedChangeAction(feed, ChangeType.DELETE);
// Remove dependent feeds
final Node node = ((JcrFeed) feed).getNode();
feed.getDependentFeeds().forEach(dep -> feed.removeDependentFeed((JcrFeed) dep));
JcrMetadataAccess.getCheckedoutNodes().removeIf(node::equals);
// Delete feed
FeedManagerTemplate template = feed.getTemplate();
if (template != null) {
template.removeFeed(feed);
}
// Remove all Ops access control entries
this.opsAccessProvider.revokeAllAccess(feed.getId());
super.delete(feed);
}
public Feed.ID resolveId(Serializable fid) {
return new JcrFeed.FeedId(fid);
}
protected JcrFeed setupPrecondition(JcrFeed feed, ServiceLevelAgreement sla) {
// this.preconditionService.watchFeed(feed);
feed.setPrecondition((JcrServiceLevelAgreement) sla);
return feed;
}
public Feed updateFeedServiceLevelAgreement(Feed.ID feedId, ServiceLevelAgreement sla) {
JcrFeed feed = (JcrFeed) getFeed(feedId);
feed.addServiceLevelAgreement(sla);
return feed;
}
@Override
public Map<String, Object> mergeFeedProperties(ID feedId, Map<String, Object> properties) {
JcrFeed feed = (JcrFeed) getFeed(feedId);
List<String> securityGroupNames = new ArrayList<>();
for (Object o : feed.getSecurityGroups()) {
HadoopSecurityGroup securityGroup = (HadoopSecurityGroup) o;
securityGroupNames.add(securityGroup.getName());
}
Map<String, Object> merged = feed.mergeProperties(properties);
PropertyChange change = new PropertyChange(feed.getId().getIdValue(),
feed.getCategory().getName(),
feed.getSystemName(),
securityGroupNames,
feed.getProperties(),
properties);
this.metadataEventService.notify(new FeedPropertyChangeEvent(change));
return merged;
}
public Map<String, Object> replaceProperties(ID feedId, Map<String, Object> properties) {
JcrFeed feed = (JcrFeed) getFeed(feedId);
return feed.replaceProperties(properties);
}
@Nonnull
@Override
public Set<UserFieldDescriptor> getUserFields() {
return JcrPropertyUtil.getUserFields(ExtensionsConstants.USER_FEED, extensibleTypeProvider);
}
@Override
public void setUserFields(@Nonnull final Set<UserFieldDescriptor> userFields) {
// TODO service?
metadataAccess.commit(() -> {
JcrPropertyUtil.setUserFields(ExtensionsConstants.USER_FEED, userFields, extensibleTypeProvider);
return userFields;
}, MetadataAccess.SERVICE);
}
public void populateInverseFeedDependencies() {
Map<Feed.ID, Feed> map = new HashMap<Feed.ID, Feed>();
List<Feed> feeds = getFeeds();
if (feeds != null) {
feeds.stream().forEach(feed -> map.put(feed.getId(), feed));
}
feeds.stream().filter(feed -> feed.getDependentFeeds() != null && !feed.getDependentFeeds().isEmpty()).forEach(feed1 -> {
List<Feed> dependentFeeds = feed1.getDependentFeeds();
dependentFeeds.stream().filter(depFeed -> depFeed.getUsedByFeeds() == null || !depFeed.getUsedByFeeds().contains(feed1))
.forEach(depFeed -> depFeed.addUsedByFeed(feed1));
});
}
private static class Criteria extends AbstractMetadataCriteria<FeedCriteria> implements FeedCriteria, Predicate<Feed> {
private String name;
private Set<Datasource.ID> sourceIds = new HashSet<>();
private Set<Datasource.ID> destIds = new HashSet<>();
private String category;
/**
* Selects by navigation rather than SQL
*/
@Override
public <E, J extends JcrObject> List<E> select(Session session, String typeName, Class<E> type, Class<J> jcrClass) {
try {
// Datasources are not currently used so only name comparison is necessary
Node feedsNode = session.getRootNode().getNode("metadata/feeds");
NodeIterator catItr = null;
if (this.category != null) {
catItr = feedsNode.getNodes(this.category);
} else {
catItr = feedsNode.getNodes();
}
List<Feed> list = new ArrayList<Feed>();
while (catItr.hasNext()) {
Node catNode = (Node) catItr.next();
NodeIterator feedItr = null;
if (catNode.hasNode(JcrCategory.DETAILS)) {
catNode = catNode.getNode(JcrCategory.DETAILS);
}
if (this.name != null) {
feedItr = catNode.getNodes(this.name);
} else {
feedItr = catNode.getNodes();
}
while (feedItr.hasNext()) {
Node feedNode = (Node) feedItr.next();
if (feedNode.getPrimaryNodeType().getName().equals("tba:feed")) {
list.add(JcrUtil.createJcrObject(feedNode, JcrFeed.class));
}
}
}
return (List<E>) list;
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Failed to select feeds", e);
}
}
@Override
@Deprecated
protected void applyFilter(StringBuilder queryStr, HashMap<String, Object> params) {
StringBuilder cond = new StringBuilder();
StringBuilder join = new StringBuilder();
if (this.name != null) {
cond.append(EntityUtil.asQueryProperty(JcrFeed.SYSTEM_NAME) + " = $name");
params.put("name", this.name);
}
if (this.category != null) {
//TODO FIX SQL
join.append(
" join [" + JcrCategory.NODE_TYPE + "] as c on e." + EntityUtil.asQueryProperty(FeedSummary.CATEGORY) + "." + EntityUtil.asQueryProperty(JcrCategory.SYSTEM_NAME) + " = c."
+ EntityUtil
.asQueryProperty(JcrCategory.SYSTEM_NAME));
cond.append(" c." + EntityUtil.asQueryProperty(JcrCategory.SYSTEM_NAME) + " = $category ");
params.put("category", this.category);
}
applyIdFilter(cond, join, this.sourceIds, "sources", params);
applyIdFilter(cond, join, this.destIds, "destinations", params);
if (join.length() > 0) {
queryStr.append(join.toString());
}
if (cond.length() > 0) {
queryStr.append(" where ").append(cond.toString());
}
}
@Deprecated
private void applyIdFilter(StringBuilder cond, StringBuilder join, Set<Datasource.ID> idSet, String relation, HashMap<String, Object> params) {
if (!idSet.isEmpty()) {
if (cond.length() > 0) {
cond.append("and ");
}
String alias = relation.substring(0, 1);
join.append("join e.").append(relation).append(" ").append(alias).append(" ");
cond.append(alias).append(".datasource.id in $").append(relation).append(" ");
params.put(relation, idSet);
}
}
@Override
public boolean apply(Feed input) {
if (this.name != null && !name.equals(input.getName())) {
return false;
}
if (this.category != null && input.getCategory() != null && !this.category.equals(input.getCategory().getName())) {
return false;
}
if (!this.destIds.isEmpty()) {
List<? extends FeedDestination> destinations = input.getDestinations();
for (FeedDestination dest : destinations) {
if (this.destIds.contains(dest.getDatasource().getId())) {
return true;
}
}
return false;
}
if (!this.sourceIds.isEmpty()) {
List<? extends FeedSource> sources = input.getSources();
for (FeedSource src : sources) {
if (this.sourceIds.contains(src.getDatasource().getId())) {
return true;
}
}
return false;
}
return true;
}
@Override
public FeedCriteria sourceDatasource(Datasource.ID id, Datasource.ID... others) {
this.sourceIds.add(id);
for (Datasource.ID other : others) {
this.sourceIds.add(other);
}
return this;
}
@Override
public FeedCriteria destinationDatasource(Datasource.ID id, Datasource.ID... others) {
this.destIds.add(id);
for (Datasource.ID other : others) {
this.destIds.add(other);
}
return this;
}
@Override
public FeedCriteria name(String name) {
this.name = name;
return this;
}
@Override
public FeedCriteria category(String category) {
this.category = category;
return this;
}
}
private class JcrPreconditionbuilder implements PreconditionBuilder {
private final ServiceLevelAgreementBuilder slaBuilder;
private final JcrFeed feed;
public JcrPreconditionbuilder(ServiceLevelAgreementBuilder slaBuilder, JcrFeed feed) {
super();
this.slaBuilder = slaBuilder;
this.feed = feed;
}
public ServiceLevelAgreementBuilder name(String name) {
return slaBuilder.name(name);
}
public ServiceLevelAgreementBuilder description(String description) {
return slaBuilder.description(description);
}
public ServiceLevelAgreementBuilder obligation(Obligation obligation) {
return slaBuilder.obligation(obligation);
}
public ObligationBuilder<ServiceLevelAgreementBuilder> obligationBuilder() {
return slaBuilder.obligationBuilder();
}
public ObligationBuilder<ServiceLevelAgreementBuilder> obligationBuilder(Condition condition) {
return slaBuilder.obligationBuilder(condition);
}
public ObligationGroupBuilder obligationGroupBuilder(Condition condition) {
return slaBuilder.obligationGroupBuilder(condition);
}
public ServiceLevelAgreement build() {
ServiceLevelAgreement sla = slaBuilder.build();
setupPrecondition(feed, sla);
return sla;
}
@Override
public ServiceLevelAgreementBuilder actionConfigurations(List<? extends ServiceLevelAgreementActionConfiguration> actionConfigurations) {
return null;
}
}
}