org.apache.unomi.services.impl.segments.SegmentServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unomi-services Show documentation
Show all versions of unomi-services Show documentation
Apache Unomi Context Server Core Services
/*
* 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
*
* 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.
*/
package org.apache.unomi.services.impl.segments;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.unomi.api.Event;
import org.apache.unomi.api.Metadata;
import org.apache.unomi.api.PartialList;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.actions.Action;
import org.apache.unomi.api.conditions.Condition;
import org.apache.unomi.api.conditions.ConditionType;
import org.apache.unomi.api.query.Query;
import org.apache.unomi.api.rules.Rule;
import org.apache.unomi.api.segments.*;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.RulesService;
import org.apache.unomi.api.services.SchedulerService;
import org.apache.unomi.api.services.SegmentService;
import org.apache.unomi.persistence.spi.CustomObjectMapper;
import org.apache.unomi.persistence.spi.aggregate.TermsAggregate;
import org.apache.unomi.services.impl.AbstractServiceImpl;
import org.apache.unomi.services.impl.ParserHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.SynchronousBundleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URL;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentService, SynchronousBundleListener {
private static final Logger logger = LoggerFactory.getLogger(SegmentServiceImpl.class.getName());
private BundleContext bundleContext;
private EventService eventService;
private RulesService rulesService;
private SchedulerService schedulerService;
private long taskExecutionPeriod = 1;
private List allSegments;
private List allScoring;
private int segmentUpdateBatchSize = 1000;
private long segmentRefreshInterval = 1000;
private int aggregateQueryBucketSize = 5000;
public SegmentServiceImpl() {
logger.info("Initializing segment service...");
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
public void setEventService(EventService eventService) {
this.eventService = eventService;
}
public void setRulesService(RulesService rulesService) {
this.rulesService = rulesService;
}
public void setSchedulerService(SchedulerService schedulerService) {
this.schedulerService = schedulerService;
}
public void setSegmentUpdateBatchSize(int segmentUpdateBatchSize) {
this.segmentUpdateBatchSize = segmentUpdateBatchSize;
}
public void setAggregateQueryBucketSize(int aggregateQueryBucketSize) {
this.aggregateQueryBucketSize = aggregateQueryBucketSize;
}
public void setSegmentRefreshInterval(long segmentRefreshInterval) {
this.segmentRefreshInterval = segmentRefreshInterval;
}
public void postConstruct() {
logger.debug("postConstruct {" + bundleContext.getBundle() + "}");
loadPredefinedSegments(bundleContext);
loadPredefinedScorings(bundleContext);
for (Bundle bundle : bundleContext.getBundles()) {
if (bundle.getBundleContext() != null && bundle.getBundleId() != bundleContext.getBundle().getBundleId()) {
loadPredefinedSegments(bundle.getBundleContext());
loadPredefinedScorings(bundle.getBundleContext());
}
}
bundleContext.addBundleListener(this);
initializeTimer();
logger.info("Segment service initialized.");
}
public void preDestroy() {
bundleContext.removeBundleListener(this);
logger.info("Segment service shutdown.");
}
private void processBundleStartup(BundleContext bundleContext) {
if (bundleContext == null) {
return;
}
loadPredefinedSegments(bundleContext);
loadPredefinedScorings(bundleContext);
}
private void processBundleStop(BundleContext bundleContext) {
if (bundleContext == null) {
return;
}
}
private void loadPredefinedSegments(BundleContext bundleContext) {
Enumeration predefinedSegmentEntries = bundleContext.getBundle().findEntries("META-INF/cxs/segments", "*.json", true);
if (predefinedSegmentEntries == null) {
return;
}
while (predefinedSegmentEntries.hasMoreElements()) {
URL predefinedSegmentURL = predefinedSegmentEntries.nextElement();
logger.debug("Found predefined segment at " + predefinedSegmentURL + ", loading... ");
try {
Segment segment = CustomObjectMapper.getObjectMapper().readValue(predefinedSegmentURL, Segment.class);
if (segment.getMetadata().getScope() == null) {
segment.getMetadata().setScope("systemscope");
}
// Register only if segment does not exist yet
if (getSegmentDefinition(segment.getMetadata().getId()) == null) {
setSegmentDefinition(segment);
logger.info("Predefined segment with id {} registered", segment.getMetadata().getId());
} else {
logger.info("The predefined segment with id {} is already registered, this segment will be skipped", segment.getMetadata().getId());
}
} catch (IOException e) {
logger.error("Error while loading segment definition " + predefinedSegmentURL, e);
}
}
}
private void loadPredefinedScorings(BundleContext bundleContext) {
Enumeration predefinedScoringEntries = bundleContext.getBundle().findEntries("META-INF/cxs/scoring", "*.json", true);
if (predefinedScoringEntries == null) {
return;
}
while (predefinedScoringEntries.hasMoreElements()) {
URL predefinedScoringURL = predefinedScoringEntries.nextElement();
logger.debug("Found predefined scoring at " + predefinedScoringURL + ", loading... ");
try {
Scoring scoring = CustomObjectMapper.getObjectMapper().readValue(predefinedScoringURL, Scoring.class);
if (scoring.getMetadata().getScope() == null) {
scoring.getMetadata().setScope("systemscope");
}
// Register only if scoring plan does not exist yet
if (getScoringDefinition(scoring.getMetadata().getId()) == null) {
setScoringDefinition(scoring);
logger.info("Predefined scoring with id {} registered", scoring.getMetadata().getId());
} else {
logger.info("The predefined scoring with id {} is already registered, this scoring will be skipped", scoring.getMetadata().getId());
}
} catch (IOException e) {
logger.error("Error while loading segment definition " + predefinedScoringURL, e);
}
}
}
public PartialList getSegmentMetadatas(int offset, int size, String sortBy) {
return getMetadatas(offset, size, sortBy, Segment.class);
}
public PartialList getSegmentMetadatas(String scope, int offset, int size, String sortBy) {
PartialList segments = persistenceService.query("metadata.scope", scope, sortBy, Segment.class, offset, size);
List details = new LinkedList<>();
for (Segment definition : segments.getList()) {
details.add(definition.getMetadata());
}
return new PartialList<>(details, segments.getOffset(), segments.getPageSize(), segments.getTotalSize(), segments.getTotalSizeRelation());
}
public PartialList getSegmentMetadatas(Query query) {
return getMetadatas(query, Segment.class);
}
private List getAllSegmentDefinitions() {
List allItems = persistenceService.getAllItems(Segment.class);
for (Segment segment : allItems) {
ParserHelper.resolveConditionType(definitionsService, segment.getCondition());
}
return allItems;
}
public Segment getSegmentDefinition(String segmentId) {
Segment definition = persistenceService.load(segmentId, Segment.class);
if (definition != null) {
ParserHelper.resolveConditionType(definitionsService, definition.getCondition());
}
return definition;
}
public void setSegmentDefinition(Segment segment) {
ParserHelper.resolveConditionType(definitionsService, segment.getCondition());
if (segment.getMetadata().isEnabled() && !segment.getMetadata().isMissingPlugins()) {
updateAutoGeneratedRules(segment.getMetadata(), segment.getCondition());
}
// make sure we update the name and description metadata that might not match, so first we remove the entry from the map
persistenceService.save(segment);
updateExistingProfilesForSegment(segment);
}
private boolean checkSegmentDeletionImpact(Condition condition, String segmentToDeleteId) {
if (condition != null) {
@SuppressWarnings("unchecked")
final List subConditions = (List) condition.getParameter("subConditions");
if (subConditions != null) {
for (Condition subCondition : subConditions) {
if (checkSegmentDeletionImpact(subCondition, segmentToDeleteId)) {
return true;
}
}
} else if ("profileSegmentCondition".equals(condition.getConditionTypeId())) {
@SuppressWarnings("unchecked")
final List referencedSegmentIds = (List) condition.getParameter("segments");
if (referencedSegmentIds.indexOf(segmentToDeleteId) >= 0) {
return true;
}
}
}
return false;
}
/**
* Return an updated condition that do not contain a condition on the segmentId anymore
* it's remove the unnecessary boolean condition (if a condition is the only one of a boolean the boolean will be remove and the subcondition returned)
* it's return null when there is no more condition after (if the condition passed was only a segment condition on the segmentId)
*
* @param condition the condition to update
* @param segmentId the segment id to remove in the condition
* @return updated condition
*/
private Condition updateSegmentDependentCondition(Condition condition, String segmentId) {
if ("booleanCondition".equals(condition.getConditionTypeId())) {
@SuppressWarnings("unchecked")
final List subConditions = (List) condition.getParameter("subConditions");
List updatedSubConditions = new LinkedList<>();
for (Condition subCondition : subConditions) {
Condition updatedCondition = updateSegmentDependentCondition(subCondition, segmentId);
if (updatedCondition != null) {
updatedSubConditions.add(updatedCondition);
}
}
if (!updatedSubConditions.isEmpty()) {
if (updatedSubConditions.size() == 1) {
return updatedSubConditions.get(0);
} else {
condition.setParameter("subConditions", updatedSubConditions);
return condition;
}
} else {
return null;
}
} else if ("profileSegmentCondition".equals(condition.getConditionTypeId())) {
@SuppressWarnings("unchecked")
final List referencedSegmentIds = (List) condition.getParameter("segments");
if (referencedSegmentIds.indexOf(segmentId) >= 0) {
referencedSegmentIds.remove(segmentId);
if (referencedSegmentIds.isEmpty()) {
return null;
} else {
condition.setParameter("segments", referencedSegmentIds);
}
}
}
return condition;
}
private Set getSegmentDependentSegments(String segmentId) {
Set impactedSegments = new HashSet<>(this.allSegments.size());
for (Segment segment : this.allSegments) {
if (checkSegmentDeletionImpact(segment.getCondition(), segmentId)) {
impactedSegments.add(segment);
}
}
return impactedSegments;
}
private Set getSegmentDependentScorings(String segmentId) {
Set impactedScoring = new HashSet<>(this.allScoring.size());
for (Scoring scoring : this.allScoring) {
for (ScoringElement element : scoring.getElements()) {
if (checkSegmentDeletionImpact(element.getCondition(), segmentId)) {
impactedScoring.add(scoring);
break;
}
}
}
return impactedScoring;
}
public DependentMetadata getSegmentDependentMetadata(String segmentId) {
List segments = new LinkedList<>();
List scorings = new LinkedList<>();
for (Segment definition : getSegmentDependentSegments(segmentId)) {
segments.add(definition.getMetadata());
}
for (Scoring definition : getSegmentDependentScorings(segmentId)) {
scorings.add(definition.getMetadata());
}
return new DependentMetadata(segments, scorings);
}
public DependentMetadata removeSegmentDefinition(String segmentId, boolean validate) {
Set impactedSegments = getSegmentDependentSegments(segmentId);
Set impactedScorings = getSegmentDependentScorings(segmentId);
if (!validate || (impactedSegments.isEmpty() && impactedScorings.isEmpty())) {
// update profiles
Condition segmentCondition = new Condition();
segmentCondition.setConditionType(definitionsService.getConditionType("profilePropertyCondition"));
segmentCondition.setParameter("propertyName", "segments");
segmentCondition.setParameter("comparisonOperator", "equals");
segmentCondition.setParameter("propertyValue", segmentId);
List previousProfiles = persistenceService.query(segmentCondition, null, Profile.class);
long updatedProfileCount = 0;
long profileRemovalStartTime = System.currentTimeMillis();
for (Profile profileToRemove : previousProfiles) {
profileToRemove.getSegments().remove(segmentId);
Map sourceMap = new HashMap<>();
sourceMap.put("segments", profileToRemove.getSegments());
profileToRemove.setSystemProperty("lastUpdated", new Date());
sourceMap.put("systemProperties", profileToRemove.getSystemProperties());
persistenceService.update(profileToRemove.getItemId(), null, Profile.class, sourceMap);
updatedProfileCount++;
}
logger.info("Removed segment from {} profiles in {} ms", updatedProfileCount, System.currentTimeMillis() - profileRemovalStartTime);
// update impacted segments
for (Segment segment : impactedSegments) {
Condition updatedCondition = updateSegmentDependentCondition(segment.getCondition(), segmentId);
segment.setCondition(updatedCondition);
if (updatedCondition == null) {
clearAutoGeneratedRules(persistenceService.query("linkedItems", segment.getMetadata().getId(), null, Rule.class), segment.getMetadata().getId());
segment.getMetadata().setEnabled(false);
}
setSegmentDefinition(segment);
}
// update impacted scorings
for (Scoring scoring : impactedScorings) {
List updatedScoringElements = new ArrayList<>();
for (ScoringElement scoringElement : scoring.getElements()) {
Condition updatedCondition = updateSegmentDependentCondition(scoringElement.getCondition(), segmentId);
if (updatedCondition != null) {
scoringElement.setCondition(updatedCondition);
updatedScoringElements.add(scoringElement);
}
}
scoring.setElements(updatedScoringElements);
if (updatedScoringElements.isEmpty()) {
clearAutoGeneratedRules(persistenceService.query("linkedItems", scoring.getMetadata().getId(), null, Rule.class), scoring.getMetadata().getId());
scoring.getMetadata().setEnabled(false);
}
setScoringDefinition(scoring);
}
persistenceService.remove(segmentId, Segment.class);
List previousRules = persistenceService.query("linkedItems", segmentId, null, Rule.class);
clearAutoGeneratedRules(previousRules, segmentId);
}
List segments = new LinkedList<>();
List scorings = new LinkedList<>();
for (Segment definition : impactedSegments) {
segments.add(definition.getMetadata());
}
for (Scoring definition : impactedScorings) {
scorings.add(definition.getMetadata());
}
return new DependentMetadata(segments, scorings);
}
public PartialList getMatchingIndividuals(String segmentID, int offset, int size, String sortBy) {
Segment segment = getSegmentDefinition(segmentID);
if (segment == null) {
return new PartialList();
}
Condition segmentCondition = new Condition(definitionsService.getConditionType("profilePropertyCondition"));
segmentCondition.setParameter("propertyName", "segments");
segmentCondition.setParameter("comparisonOperator", "equals");
segmentCondition.setParameter("propertyValue", segmentID);
return persistenceService.query(segmentCondition, sortBy, Profile.class, offset, size);
}
public long getMatchingIndividualsCount(String segmentID) {
if (getSegmentDefinition(segmentID) == null) {
return 0;
}
Condition segmentCondition = new Condition(definitionsService.getConditionType("profilePropertyCondition"));
segmentCondition.setParameter("propertyName", "segments");
segmentCondition.setParameter("comparisonOperator", "equals");
segmentCondition.setParameter("propertyValue", segmentID);
return persistenceService.queryCount(segmentCondition, Profile.ITEM_TYPE);
}
public Boolean isProfileInSegment(Profile profile, String segmentId) {
Set matchingSegments = getSegmentsAndScoresForProfile(profile).getSegments();
return matchingSegments.contains(segmentId);
}
public SegmentsAndScores getSegmentsAndScoresForProfile(Profile profile) {
Set segments = new HashSet();
Map scores = new HashMap();
List allSegments = this.allSegments;
for (Segment segment : allSegments) {
if (segment.getMetadata().isEnabled() && persistenceService.testMatch(segment.getCondition(), profile)) {
segments.add(segment.getMetadata().getId());
}
}
List allScoring = this.allScoring;
Map scoreModifiers = (Map) profile.getSystemProperties().get("scoreModifiers");
for (Scoring scoring : allScoring) {
if (scoring.getMetadata().isEnabled()) {
int score = 0;
for (ScoringElement scoringElement : scoring.getElements()) {
if (persistenceService.testMatch(scoringElement.getCondition(), profile)) {
score += scoringElement.getValue();
}
}
String scoringId = scoring.getMetadata().getId();
if (scoreModifiers != null && scoreModifiers.containsKey(scoringId) && scoreModifiers.get(scoringId) != null) {
score += scoreModifiers.get(scoringId);
}
scores.put(scoringId, score);
}
}
return new SegmentsAndScores(segments, scores);
}
public List getSegmentMetadatasForProfile(Profile profile) {
List metadatas = new ArrayList<>();
List allSegments = this.allSegments;
for (Segment segment : allSegments) {
if (persistenceService.testMatch(segment.getCondition(), profile)) {
metadatas.add(segment.getMetadata());
}
}
return metadatas;
}
public PartialList getScoringMetadatas(int offset, int size, String sortBy) {
return getMetadatas(offset, size, sortBy, Scoring.class);
}
public PartialList getScoringMetadatas(Query query) {
return getMetadatas(query, Scoring.class);
}
private List getAllScoringDefinitions() {
List allItems = persistenceService.getAllItems(Scoring.class);
for (Scoring scoring : allItems) {
for (ScoringElement element : scoring.getElements()) {
ParserHelper.resolveConditionType(definitionsService, element.getCondition());
}
}
return allItems;
}
public Scoring getScoringDefinition(String scoringId) {
Scoring definition = persistenceService.load(scoringId, Scoring.class);
if (definition != null) {
for (ScoringElement element : definition.getElements()) {
ParserHelper.resolveConditionType(definitionsService, element.getCondition());
}
}
return definition;
}
public void setScoringDefinition(Scoring scoring) {
for (ScoringElement element : scoring.getElements()) {
ParserHelper.resolveConditionType(definitionsService, element.getCondition());
}
for (ScoringElement element : scoring.getElements()) {
if (scoring.getMetadata().isEnabled() && !scoring.getMetadata().isMissingPlugins()) {
updateAutoGeneratedRules(scoring.getMetadata(), element.getCondition());
}
}
// make sure we update the name and description metadata that might not match, so first we remove the entry from the map
persistenceService.save(scoring);
persistenceService.createMapping(Profile.ITEM_TYPE, String.format(
"{\n" +
" \"properties\": {\n" +
" \"scores\": {\n" +
" \"properties\": {\n" +
" \"%s\": {\n" +
" \"type\":\"long\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}", scoring.getItemId()));
updateExistingProfilesForScoring(scoring);
}
public void createScoringDefinition(String scope, String scoringId, String name, String description) {
Metadata metadata = new Metadata(scope, scoringId, name, description);
Scoring scoring = new Scoring(metadata);
Condition rootCondition = new Condition();
rootCondition.setConditionType(definitionsService.getConditionType("booleanCondition"));
rootCondition.setParameter("operator", "and");
rootCondition.setParameter("subConditions", new ArrayList());
scoring.setElements(new ArrayList());
setScoringDefinition(scoring);
}
private boolean checkScoringDeletionImpact(Condition condition, String scoringToDeleteId) {
if (condition != null) {
@SuppressWarnings("unchecked")
final List subConditions = (List) condition.getParameter("subConditions");
if (subConditions != null) {
for (Condition subCondition : subConditions) {
if (checkScoringDeletionImpact(subCondition, scoringToDeleteId)) {
return true;
}
}
} else if ("scoringCondition".equals(condition.getConditionTypeId())) {
if (scoringToDeleteId.equals(condition.getParameter("scoringPlanId"))) {
return true;
}
}
}
return false;
}
/**
* Return an updated condition that do not contain a condition on the scoringId anymore
* it's remove the unnecessary boolean condition (if a condition is the only one of a boolean the boolean will be remove and the subcondition returned)
* it's return null when there is no more condition after (if the condition passed was only a scoring condition on the scoringId)
*
* @param condition the condition to update
* @param scoringId the scoring id to remove in the condition
* @return updated condition
*/
private Condition updateScoringDependentCondition(Condition condition, String scoringId) {
if ("booleanCondition".equals(condition.getConditionTypeId())) {
@SuppressWarnings("unchecked")
final List subConditions = (List) condition.getParameter("subConditions");
List updatedSubConditions = new LinkedList<>();
for (Condition subCondition : subConditions) {
Condition updatedCondition = updateScoringDependentCondition(subCondition, scoringId);
if (updatedCondition != null) {
updatedSubConditions.add(updatedCondition);
}
}
if (!updatedSubConditions.isEmpty()) {
if (updatedSubConditions.size() == 1) {
return updatedSubConditions.get(0);
} else {
condition.setParameter("subConditions", updatedSubConditions);
return condition;
}
} else {
return null;
}
} else if ("scoringCondition".equals(condition.getConditionTypeId())
&& scoringId.equals(condition.getParameter("scoringPlanId"))) {
return null;
}
return condition;
}
private Set getScoringDependentSegments(String scoringId) {
Set impactedSegments = new HashSet<>(this.allSegments.size());
for (Segment segment : this.allSegments) {
if (checkScoringDeletionImpact(segment.getCondition(), scoringId)) {
impactedSegments.add(segment);
}
}
return impactedSegments;
}
private Set getScoringDependentScorings(String scoringId) {
Set impactedScoring = new HashSet<>(this.allScoring.size());
for (Scoring scoring : this.allScoring) {
for (ScoringElement element : scoring.getElements()) {
if (checkScoringDeletionImpact(element.getCondition(), scoringId)) {
impactedScoring.add(scoring);
break;
}
}
}
return impactedScoring;
}
public DependentMetadata getScoringDependentMetadata(String scoringId) {
List segments = new LinkedList<>();
List scorings = new LinkedList<>();
for (Segment definition : getScoringDependentSegments(scoringId)) {
segments.add(definition.getMetadata());
}
for (Scoring definition : getScoringDependentScorings(scoringId)) {
scorings.add(definition.getMetadata());
}
return new DependentMetadata(segments, scorings);
}
public DependentMetadata removeScoringDefinition(String scoringId, boolean validate) {
Set impactedSegments = getScoringDependentSegments(scoringId);
Set impactedScorings = getScoringDependentScorings(scoringId);
if (!validate || (impactedSegments.isEmpty() && impactedScorings.isEmpty())) {
// update profiles
updateExistingProfilesForRemovedScoring(scoringId);
// update impacted segments
for (Segment segment : impactedSegments) {
Condition updatedCondition = updateScoringDependentCondition(segment.getCondition(), scoringId);
segment.setCondition(updatedCondition);
if (updatedCondition == null) {
clearAutoGeneratedRules(persistenceService.query("linkedItems", segment.getMetadata().getId(), null, Rule.class), segment.getMetadata().getId());
segment.getMetadata().setEnabled(false);
}
setSegmentDefinition(segment);
}
// update impacted scorings
for (Scoring scoring : impactedScorings) {
List updatedScoringElements = new ArrayList<>();
for (ScoringElement scoringElement : scoring.getElements()) {
Condition updatedCondition = updateScoringDependentCondition(scoringElement.getCondition(), scoringId);
if (updatedCondition != null) {
scoringElement.setCondition(updatedCondition);
updatedScoringElements.add(scoringElement);
}
}
scoring.setElements(updatedScoringElements);
if (updatedScoringElements.isEmpty()) {
clearAutoGeneratedRules(persistenceService.query("linkedItems", scoring.getMetadata().getId(), null, Rule.class), scoring.getMetadata().getId());
scoring.getMetadata().setEnabled(false);
}
setScoringDefinition(scoring);
}
persistenceService.remove(scoringId, Scoring.class);
List previousRules = persistenceService.query("linkedItems", scoringId, null, Rule.class);
clearAutoGeneratedRules(previousRules, scoringId);
}
List segments = new LinkedList<>();
List scorings = new LinkedList<>();
for (Segment definition : impactedSegments) {
segments.add(definition.getMetadata());
}
for (Scoring definition : impactedScorings) {
scorings.add(definition.getMetadata());
}
return new DependentMetadata(segments, scorings);
}
public void updateAutoGeneratedRules(Metadata metadata, Condition condition) {
List previousRules = persistenceService.query("linkedItems", metadata.getId(), null, Rule.class);
List rules = new ArrayList();
if (condition != null) {
getAutoGeneratedRules(metadata, condition, null, rules);
}
for (Rule rule : rules) {
rulesService.setRule(rule);
}
previousRules.removeAll(rules);
clearAutoGeneratedRules(previousRules, metadata.getId());
}
private void clearAutoGeneratedRules(List rules, String idWithScope) {
for (Rule previousRule : rules) {
previousRule.getLinkedItems().remove(idWithScope);
if (previousRule.getLinkedItems().isEmpty()) {
// todo remove profile properties ?
persistenceService.remove(previousRule.getItemId(), Rule.class);
} else {
persistenceService.update(previousRule.getItemId(), null, Rule.class, "linkedItems", previousRule.getLinkedItems());
}
}
}
private void getAutoGeneratedRules(Metadata metadata, Condition condition, Condition parentCondition, List rules) {
Set tags = condition.getConditionType().getMetadata().getSystemTags();
if (tags.contains("eventCondition") && !tags.contains("profileCondition")) {
String key = getGeneratedPropertyKey(condition, parentCondition);
if (key != null) {
parentCondition.setParameter("generatedPropertyKey", key);
Rule rule = rulesService.getRule(key);
if (rule == null) {
rule = new Rule(new Metadata(metadata.getScope(), key, "Auto generated rule for " + metadata.getName(), ""));
rule.setCondition(condition);
rule.getMetadata().setHidden(true);
final Action action = new Action();
action.setActionType(definitionsService.getActionType("setEventOccurenceCountAction"));
action.setParameter("pastEventCondition", parentCondition);
rule.setActions(Arrays.asList(action));
rule.setLinkedItems(Arrays.asList(metadata.getId()));
rules.add(rule);
updateExistingProfilesForPastEventCondition(condition, parentCondition);
} else {
rule.getLinkedItems().add(metadata.getId());
rules.add(rule);
}
}
} else {
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy