You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by ql...@apache.org on 2016/08/12 14:16:06 UTC
incubator-unomi git commit: UNOMI-48: Add/improve validation done at
scoring/segment deletion
Repository: incubator-unomi
Updated Branches:
refs/heads/master 1c5d74aa5 -> 30a51a23d
UNOMI-48: Add/improve validation done at scoring/segment deletion
Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/30a51a23
Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/30a51a23
Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/30a51a23
Branch: refs/heads/master
Commit: 30a51a23dc73c6c6c794056aeeed2108c146bc60
Parents: 1c5d74a
Author: Quentin Lamerand <ql...@jahia.com>
Authored: Fri Aug 12 16:15:56 2016 +0200
Committer: Quentin Lamerand <ql...@jahia.com>
Committed: Fri Aug 12 16:15:56 2016 +0200
----------------------------------------------------------------------
.../unomi/api/segments/DependentMetadata.java | 53 +++++
.../unomi/api/services/SegmentService.java | 41 ++--
.../cxs/conditions/scoringCondition.json | 40 ++++
.../unomi/rest/ScoringServiceEndPoint.java | 29 ++-
.../unomi/rest/SegmentServiceEndPoint.java | 23 +-
.../services/services/SegmentServiceImpl.java | 230 ++++++++++++++++---
6 files changed, 358 insertions(+), 58 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/30a51a23/api/src/main/java/org/apache/unomi/api/segments/DependentMetadata.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/unomi/api/segments/DependentMetadata.java b/api/src/main/java/org/apache/unomi/api/segments/DependentMetadata.java
new file mode 100644
index 0000000..a6693f3
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/segments/DependentMetadata.java
@@ -0,0 +1,53 @@
+/*
+ * 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.api.segments;
+
+import org.apache.unomi.api.Metadata;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.List;
+
+@XmlRootElement
+public class DependentMetadata implements Serializable {
+
+ private List<Metadata> segments;
+
+ private List<Metadata> scorings;
+
+ public DependentMetadata(List<Metadata> segments, List<Metadata> scorings) {
+ this.segments = segments;
+ this.scorings = scorings;
+ }
+
+ public List<Metadata> getSegments() {
+ return segments;
+ }
+
+ public void setSegments(List<Metadata> segments) {
+ this.segments = segments;
+ }
+
+ public List<Metadata> getScorings() {
+ return scorings;
+ }
+
+ public void setScorings(List<Metadata> scorings) {
+ this.scorings = scorings;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/30a51a23/api/src/main/java/org/apache/unomi/api/services/SegmentService.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/unomi/api/services/SegmentService.java b/api/src/main/java/org/apache/unomi/api/services/SegmentService.java
index 8c1db29..a1affd6 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SegmentService.java
+++ b/api/src/main/java/org/apache/unomi/api/services/SegmentService.java
@@ -22,6 +22,7 @@ import org.apache.unomi.api.Metadata;
import org.apache.unomi.api.PartialList;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.query.Query;
+import org.apache.unomi.api.segments.DependentMetadata;
import org.apache.unomi.api.segments.Scoring;
import org.apache.unomi.api.segments.Segment;
import org.apache.unomi.api.segments.SegmentsAndScores;
@@ -88,25 +89,23 @@ public interface SegmentService {
/**
* Removes the segment definition identified by the specified identifier. We can specify that we want the operation to be validated beforehand so that we can
* know if any other segment that might use the segment we're trying to delete as a condition might be impacted. If {@code validate} is set to {@code false}, no
- * validation is performed. If set to {@code true}, we will first check if any segment depends on the one we're trying to delete and if so we will not delete the
- * segment but rather return the list of the metadata of the impacted segments. If no dependents are found, then we properly delete the segment.
+ * validation is performed. If set to {@code true}, we will first check if any segment or scoring depends on the segment we're trying to delete and if so we will not delete the
+ * segment but rather return the list of the metadata of the impacted items. If no dependents are found, then we properly delete the segment.
*
* @param segmentId the identifier of the segment we want to delete
* @param validate whether or not to perform validation
- * @return a list of impacted segment metadata if any or an empty list if no such impacted segments are found or validation was skipped
+ * @return a list of impacted segment metadata if any or an empty list if none were found or validation was skipped
*/
- List<Metadata> removeSegmentDefinition(String segmentId, boolean validate);
+ DependentMetadata removeSegmentDefinition(String segmentId, boolean validate);
/**
- * Retrieves the list of segment metadata of segments depending on the segment identified by the specified identifier. A segment is depending on another one if it includes
- * that segment as part of its condition for profile matching.
+ * Retrieves the list of Segment and Scoring metadata depending on the specified segment.
+ * A segment or scoring is depending on a segment if it includes a profileSegmentCondition with a test on this segment.
*
- * TODO: Rename to something clearer, maybe getDependentSegmentMetadata?
- *
- * @param segmentId the identifier of the segment which impact we want to evaluate
- * @return a list of metadata of segments depending on the specified segment
+ * @param segmentId the segment identifier
+ * @return a list of Segment/Scoring Metadata depending on the specified segment
*/
- List<Metadata> getImpactedSegmentMetadata(String segmentId);
+ DependentMetadata getSegmentDependentMetadata(String segmentId);
/**
* Retrieves a list of profiles matching the conditions defined by the segment identified by the specified identifier, ordered according to the specified {@code sortBy}
@@ -197,10 +196,24 @@ public interface SegmentService {
void createScoringDefinition(String scope, String scoringId, String name, String description);
/**
- * Deletes the scoring identified by the specified identifier from the context server.
+ * Removes the scoring definition identified by the specified identifier. We can specify that we want the operation to be validated beforehand so that we can
+ * know if any other segment that might use the segment we're trying to delete as a condition might be impacted. If {@code validate} is set to {@code false}, no
+ * validation is performed. If set to {@code true}, we will first check if any segment or scoring depends on the scoring we're trying to delete and if so we will not delete the
+ * scoring but rather return the list of the metadata of the impacted items. If no dependents are found, then we properly delete the scoring.
+ *
+ * @param scoringId the identifier of the scoring we want to delete
+ * @param validate whether or not to perform validation
+ * @return a list of impacted items metadata if any or an empty list if none were found or validation was skipped
+ */
+ DependentMetadata removeScoringDefinition(String scoringId, boolean validate);
+
+ /**
+ * Retrieves the list of Segment and Scoring metadata depending on the specified scoring.
+ * A segment or scoring is depending on a segment if it includes a scoringCondition with a test on this scoring.
*
- * @param scoringId the identifier of the scoring to be deleted
+ * @param scoringId the segment identifier
+ * @return a list of Segment/Scoring Metadata depending on the specified scoring
*/
- void removeScoringDefinition(String scoringId);
+ DependentMetadata getScoringDependentMetadata(String scoringId);
}
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/30a51a23/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/scoringCondition.json
----------------------------------------------------------------------
diff --git a/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/scoringCondition.json b/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/scoringCondition.json
new file mode 100644
index 0000000..6ef37fc
--- /dev/null
+++ b/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions/scoringCondition.json
@@ -0,0 +1,40 @@
+{
+ "metadata": {
+ "id": "scoringCondition",
+ "name": "scoringCondition",
+ "description": "",
+ "tags": [
+ "aggregated",
+ "profileCondition"
+ ],
+ "readOnly": true
+ },
+ "parentCondition": {
+ "type": "profilePropertyCondition",
+ "parameterValues": {
+ "propertyName": "script::'scores.'+scoringPlanId",
+ "propertyValueInteger": "parameter::scoreValue",
+ "comparisonOperator": "parameter::comparisonOperator"
+ }
+ },
+ "parameters": [
+ {
+ "id": "scoringPlanId",
+ "type": "string",
+ "multivalued": false,
+ "defaultValue": ""
+ },
+ {
+ "id": "scoreValue",
+ "type": "integer",
+ "multivalued": false,
+ "defaultValue": 0
+ },
+ {
+ "id": "comparisonOperator",
+ "type": "string",
+ "multivalued": false,
+ "defaultValue": "greaterThanOrEqualTo"
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/30a51a23/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
index 0865b8d..e8307bd 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
@@ -22,6 +22,7 @@ import org.apache.unomi.api.Item;
import org.apache.unomi.api.Metadata;
import org.apache.unomi.api.PartialList;
import org.apache.unomi.api.query.Query;
+import org.apache.unomi.api.segments.DependentMetadata;
import org.apache.unomi.api.segments.Scoring;
import org.apache.unomi.api.services.SegmentService;
@@ -117,14 +118,32 @@ public class ScoringServiceEndPoint {
}
/**
- * Deletes the scoring identified by the specified identifier from the context server.
+ * Removes the scoring definition identified by the specified identifier. We can specify that we want the operation to be validated beforehand so that we can
+ * know if any other segment that might use the segment we're trying to delete as a condition might be impacted. If {@code validate} is set to {@code false}, no
+ * validation is performed. If set to {@code true}, we will first check if any segment or scoring depends on the scoring we're trying to delete and if so we will not delete the
+ * scoring but rather return the list of the metadata of the impacted items. If no dependents are found, then we properly delete the scoring.
*
- * @param scoringId the identifier of the scoring to be deleted
+ * @param scoringId the identifier of the scoring we want to delete
+ * @param validate whether or not to perform validation
+ * @return a list of impacted items metadata if any or an empty list if none were found or validation was skipped
*/
- @DELETE
+ @DELETE
@Path("/{scoringID}")
- public void removeScoringDefinition(@PathParam("scoringID") String scoringId) {
- segmentService.removeScoringDefinition(scoringId);
+ public DependentMetadata removeScoringDefinition(@PathParam("scoringID") String scoringId, @QueryParam("validate") boolean validate) {
+ return segmentService.removeScoringDefinition(scoringId, validate);
+ }
+
+ /**
+ * Retrieves the list of Segment and Scoring metadata depending on the specified scoring.
+ * A segment or scoring is depending on a segment if it includes a scoringCondition with a test on this scoring.
+ *
+ * @param scoringId the segment identifier
+ * @return a list of Segment/Scoring Metadata depending on the specified scoring
+ */
+ @GET
+ @Path("/{scoringID}/impacted")
+ public DependentMetadata getScoringDependentMetadata(@PathParam("scoringID") String scoringId) {
+ return segmentService.getScoringDependentMetadata(scoringId);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/30a51a23/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
index c74c370..7c1e573 100644
--- a/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
@@ -22,6 +22,7 @@ import org.apache.unomi.api.Metadata;
import org.apache.unomi.api.PartialList;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.query.Query;
+import org.apache.unomi.api.segments.DependentMetadata;
import org.apache.unomi.api.segments.Segment;
import org.apache.unomi.api.services.SegmentService;
@@ -110,18 +111,16 @@ public class SegmentServiceEndPoint {
}
/**
- * Retrieves the list of segment metadata of segments depending on the segment identified by the specified identifier. A segment is depending on another one if it includes
- * that segment as part of its condition for profile matching.
+ * Retrieves the list of Segment and Scoring metadata depending on the specified segment.
+ * A segment or scoring is depending on a segment if it includes a profileSegmentCondition with a test on this segment.
*
- * TODO: rename?
- *
- * @param segmentId the identifier of the segment which impact we want to evaluate
- * @return a list of metadata of segments depending on the specified segment
+ * @param segmentId the segment identifier
+ * @return a list of Segment/Scoring Metadata depending on the specified segment
*/
@GET
@Path("/{segmentID}/impacted")
- public List<Metadata> getSegmentImpacted(@PathParam("segmentID") String segmentId) {
- return segmentService.getImpactedSegmentMetadata(segmentId);
+ public DependentMetadata getSegmentDependentMetadata(@PathParam("segmentID") String segmentId) {
+ return segmentService.getSegmentDependentMetadata(segmentId);
}
/**
@@ -162,16 +161,16 @@ public class SegmentServiceEndPoint {
/**
* Removes the segment definition identified by the specified identifier. We can specify that we want the operation to be validated beforehand so that we can
* know if any other segment that might use the segment we're trying to delete as a condition might be impacted. If {@code validate} is set to {@code false}, no
- * validation is performed. If set to {@code true}, we will first check if any segment depends on the one we're trying to delete and if so we will not delete the
- * segment but rather return the list of the metadata of the impacted segments. If no dependents are found, then we properly delete the segment.
+ * validation is performed. If set to {@code true}, we will first check if any segment or scoring depends on the segment we're trying to delete and if so we will not delete the
+ * segment but rather return the list of the metadata of the impacted items. If no dependents are found, then we properly delete the segment.
*
* @param segmentId the identifier of the segment we want to delete
* @param validate whether or not to perform validation
- * @return a list of impacted segment metadata if any or an empty list if no such impacted segments are found or validation was skipped
+ * @return a list of impacted segment metadata if any or an empty list if none were found or validation was skipped
*/
@DELETE
@Path("/{segmentID}")
- public List<Metadata> removeSegmentDefinition(@PathParam("segmentID") String segmentId, @QueryParam("validate") boolean validate) {
+ public DependentMetadata removeSegmentDefinition(@PathParam("segmentID") String segmentId, @QueryParam("validate") boolean validate) {
return segmentService.removeSegmentDefinition(segmentId, validate);
}
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/30a51a23/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
index 6149f62..bd68971 100644
--- a/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
@@ -21,13 +21,9 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.unomi.api.*;
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.Scoring;
-import org.apache.unomi.api.segments.ScoringElement;
-import org.apache.unomi.api.segments.Segment;
-import org.apache.unomi.api.segments.SegmentsAndScores;
+import org.apache.unomi.api.segments.*;
import org.apache.unomi.api.services.DefinitionsService;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.RulesService;
@@ -253,23 +249,26 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
updateExistingProfilesForSegment(segment);
}
- private void checkIfSegmentIsImpacted(Segment segment, Condition condition, String segmentToDeleteId, Set<Segment> impactedSegments) {
+ private boolean checkSegmentDeletionImpact(Condition condition, String segmentToDeleteId) {
if(condition != null) {
@SuppressWarnings("unchecked")
final List<Condition> subConditions = (List<Condition>) condition.getParameter("subConditions");
if (subConditions != null) {
for (Condition subCondition : subConditions) {
- checkIfSegmentIsImpacted(segment, subCondition, segmentToDeleteId, impactedSegments);
+ if (checkSegmentDeletionImpact(subCondition, segmentToDeleteId)) {
+ return true;
+ }
}
} else if ("profileSegmentCondition".equals(condition.getConditionTypeId())) {
@SuppressWarnings("unchecked")
final List<String> referencedSegmentIds = (List<String>) condition.getParameter("segments");
if (referencedSegmentIds.indexOf(segmentToDeleteId) >= 0) {
- impactedSegments.add(segment);
+ return true;
}
}
}
+ return false;
}
/**
@@ -280,13 +279,13 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
* @param segmentId the segment id to remove in the condition
* @return updated condition
*/
- private Condition updateImpactedCondition(Condition condition, String segmentId) {
+ private Condition updateSegmentDependentCondition(Condition condition, String segmentId) {
if ("booleanCondition".equals(condition.getConditionTypeId())) {
@SuppressWarnings("unchecked")
final List<Condition> subConditions = (List<Condition>) condition.getParameter("subConditions");
List<Condition> updatedSubConditions = new LinkedList<>();
for (Condition subCondition : subConditions) {
- Condition updatedCondition = updateImpactedCondition(subCondition, segmentId);
+ Condition updatedCondition = updateSegmentDependentCondition(subCondition, segmentId);
if(updatedCondition != null) {
updatedSubConditions.add(updatedCondition);
}
@@ -316,26 +315,45 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
return condition;
}
- private Set<Segment> getImpactedSegments(String segmentId) {
+ private Set<Segment> getSegmentDependentSegments(String segmentId) {
Set<Segment> impactedSegments = new HashSet<>(this.allSegments.size());
for (Segment segment : this.allSegments) {
- checkIfSegmentIsImpacted(segment, segment.getCondition(), segmentId, impactedSegments);
+ if (checkSegmentDeletionImpact(segment.getCondition(), segmentId)) {
+ impactedSegments.add(segment);
+ }
}
return impactedSegments;
}
- public List<Metadata> getImpactedSegmentMetadata(String segmentId) {
- List<Metadata> details = new LinkedList<>();
- for (Segment definition : getImpactedSegments(segmentId)) {
- details.add(definition.getMetadata());
+ private Set<Scoring> getSegmentDependentScorings(String segmentId) {
+ Set<Scoring> 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;
+ }
- return details;
+ public DependentMetadata getSegmentDependentMetadata(String segmentId) {
+ List<Metadata> segments = new LinkedList<>();
+ List<Metadata> 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 List<Metadata> removeSegmentDefinition(String segmentId, boolean validate) {
- Set<Segment> impactedSegments = getImpactedSegments(segmentId);
- if (!validate || impactedSegments.isEmpty()) {
+ public DependentMetadata removeSegmentDefinition(String segmentId, boolean validate) {
+ Set<Segment> impactedSegments = getSegmentDependentSegments(segmentId);
+ Set<Scoring> impactedScorings = getSegmentDependentScorings(segmentId);
+ if (!validate || (impactedSegments.isEmpty() && impactedScorings.isEmpty())) {
// update profiles
Condition segmentCondition = new Condition();
segmentCondition.setConditionType(definitionsService.getConditionType("profilePropertyCondition"));
@@ -351,7 +369,7 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
// update impacted segments
for (Segment segment : impactedSegments) {
- Condition updatedCondition = updateImpactedCondition(segment.getCondition(), segmentId);
+ 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());
@@ -360,16 +378,38 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
setSegmentDefinition(segment);
}
+ // update impacted scorings
+ for (Scoring scoring : impactedScorings) {
+ List<ScoringElement> 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<Rule> previousRules = persistenceService.query("linkedItems", segmentId, null, Rule.class);
clearAutoGeneratedRules(previousRules, segmentId);
}
- List<Metadata> metadata = new LinkedList<>();
+ List<Metadata> segments = new LinkedList<>();
+ List<Metadata> scorings = new LinkedList<>();
for (Segment definition : impactedSegments) {
- metadata.add(definition.getMetadata());
+ segments.add(definition.getMetadata());
+ }
+ for (Scoring definition : impactedScorings) {
+ scorings.add(definition.getMetadata());
}
- return metadata;
+ return new DependentMetadata(segments, scorings);
}
@@ -504,10 +544,146 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
setScoringDefinition(scoring);
}
- public void removeScoringDefinition(String scoringId) {
- persistenceService.remove(scoringId, Scoring.class);
+ private boolean checkScoringDeletionImpact(Condition condition, String scoringToDeleteId) {
+ if(condition != null) {
+ @SuppressWarnings("unchecked")
+ final List<Condition> subConditions = (List<Condition>) 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<Condition> subConditions = (List<Condition>) condition.getParameter("subConditions");
+ List<Condition> 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<Segment> getScoringDependentSegments(String scoringId) {
+ Set<Segment> impactedSegments = new HashSet<>(this.allSegments.size());
+ for (Segment segment : this.allSegments) {
+ if (checkScoringDeletionImpact(segment.getCondition(), scoringId)) {
+ impactedSegments.add(segment);
+ }
+ }
+ return impactedSegments;
+ }
+
+ private Set<Scoring> getScoringDependentScorings(String scoringId) {
+ Set<Scoring> 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<Metadata> segments = new LinkedList<>();
+ List<Metadata> 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<Segment> impactedSegments = getScoringDependentSegments(scoringId);
+ Set<Scoring> 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<ScoringElement> 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<Rule> previousRules = persistenceService.query("linkedItems", scoringId, null, Rule.class);
+ clearAutoGeneratedRules(previousRules, scoringId);
+ }
- updateExistingProfilesForRemovedScoring(scoringId);
+ List<Metadata> segments = new LinkedList<>();
+ List<Metadata> 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) {