Repository: incubator-unomi Updated Branches: refs/heads/master f994d99a1 -> 510c524bf
UNOMI-182 make sure definitions are redeployed if the bundles that bring them is in SNAPSHOT Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/510c524b Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/510c524b Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/510c524b Branch: refs/heads/master Commit: 510c524bfe0415a1fae8d643e7cac48b667b88b9 Parents: f994d99 Author: dgaillard <[email protected]> Authored: Wed May 23 11:49:34 2018 +0200 Committer: dgaillard <[email protected]> Committed: Wed May 23 11:49:34 2018 +0200 ---------------------------------------------------------------------- .../unomi/api/services/ProfileService.java | 9 + .../services/DefinitionsServiceImpl.java | 4 +- .../services/services/GoalsServiceImpl.java | 4 +- .../services/services/ProfileServiceImpl.java | 20 +- .../services/services/RulesServiceImpl.java | 2 +- .../services/services/SegmentServiceImpl.java | 4 +- .../unomi/shell/commands/DeployDefinition.java | 183 +++++++++++++++++++ .../resources/OSGI-INF/blueprint/blueprint.xml | 15 +- 8 files changed, 225 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java index 028cc89..bc86c70 100644 --- a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java +++ b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java @@ -21,6 +21,7 @@ import org.apache.unomi.api.*; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.query.Query; +import java.net.URL; import java.util.*; /** @@ -312,6 +313,14 @@ public interface ProfileService { boolean setPropertyType(PropertyType property); /** + * This function will try to set the target on the property type if not set already, based on the file URL + * + * @param predefinedPropertyTypeURL + * @param propertyType + */ + void setPropertyTypeTarget(URL predefinedPropertyTypeURL, PropertyType propertyType); + + /** * Deletes the property type identified by the specified identifier. * * TODO: move to a different class http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java index b5f8166..3392522 100644 --- a/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java @@ -132,7 +132,7 @@ public class DefinitionsServiceImpl implements DefinitionsService, SynchronousBu try { ConditionType conditionType = CustomObjectMapper.getObjectMapper().readValue(predefinedConditionURL, ConditionType.class); // Register only if condition type does not exist yet - if (getConditionType(conditionType.getMetadata().getId()) == null) { + if (getConditionType(conditionType.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setConditionType(conditionType); logger.info("Predefined condition type with id {} registered", conditionType.getMetadata().getId()); } else { @@ -157,7 +157,7 @@ public class DefinitionsServiceImpl implements DefinitionsService, SynchronousBu try { ActionType actionType = CustomObjectMapper.getObjectMapper().readValue(predefinedActionURL, ActionType.class); // Register only if action type does not exist yet - if (getActionType(actionType.getMetadata().getId()) == null) { + if (getActionType(actionType.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setActionType(actionType); logger.info("Predefined action type with id {} registered", actionType.getMetadata().getId()); } else { http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java index f9bd9c3..bd7fce5 100644 --- a/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java @@ -119,7 +119,7 @@ public class GoalsServiceImpl implements GoalsService, SynchronousBundleListener goal.getMetadata().setScope("systemscope"); } // Register only if goal does not exist yet - if (getGoal(goal.getMetadata().getId()) == null) { + if (getGoal(goal.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setGoal(goal); logger.info("Predefined goal with id {} registered", goal.getMetadata().getId()); } else { @@ -264,7 +264,7 @@ public class GoalsServiceImpl implements GoalsService, SynchronousBundleListener try { Campaign campaign = CustomObjectMapper.getObjectMapper().readValue(predefinedCampaignURL, Campaign.class); // Register only if campaign does not exist yet - if (getCampaign(campaign.getMetadata().getId()) == null) { + if (getCampaign(campaign.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setCampaign(campaign); logger.info("Predefined campaign with id {} registered", campaign.getMetadata().getId()); } else { http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java index a37ed7a..bdce139 100644 --- a/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java @@ -896,6 +896,16 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList return null; } + public void setPropertyTypeTarget(URL predefinedPropertyTypeURL, PropertyType propertyType) { + if (StringUtils.isBlank(propertyType.getTarget())) { + String[] splitPath = predefinedPropertyTypeURL.getPath().split("/"); + String target = splitPath[4]; + if (StringUtils.isNotBlank(target)) { + propertyType.setTarget(target); + } + } + } + private void loadPredefinedPersonas(BundleContext bundleContext) { if (bundleContext == null) { return; @@ -914,7 +924,7 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList String itemId = persona.getPersona().getItemId(); // Register only if persona does not exist yet - if (persistenceService.load(itemId, Persona.class) == null) { + if (persistenceService.load(itemId, Persona.class) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { persistenceService.save(persona.getPersona()); List<PersonaSession> sessions = persona.getSessions(); @@ -947,10 +957,9 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList try { PropertyType propertyType = CustomObjectMapper.getObjectMapper().readValue(predefinedPropertyTypeURL, PropertyType.class); // Register only if property type does not exist yet - if (getPropertyType(propertyType.getMetadata().getId()) == null) { - String[] splitPath = predefinedPropertyTypeURL.getPath().split("/"); - String target = splitPath[4]; - propertyType.setTarget(target); + if (getPropertyType(propertyType.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { + + setPropertyTypeTarget(predefinedPropertyTypeURL, propertyType); persistenceService.save(propertyType); bundlePropertyTypes.add(propertyType); @@ -965,7 +974,6 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList propertyTypes = propertyTypes.with(bundlePropertyTypes); } - public void bundleChanged(BundleEvent event) { switch (event.getType()) { case BundleEvent.STARTED: http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java index d3758ba..2bcf564 100644 --- a/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java @@ -153,7 +153,7 @@ public class RulesServiceImpl implements RulesService, EventListenerService, Syn try { Rule rule = CustomObjectMapper.getObjectMapper().readValue(predefinedSegmentURL, Rule.class); // Register only if rule does not exist yet - if (getRule(rule.getMetadata().getId()) == null) { + if (getRule(rule.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setRule(rule); logger.info("Predefined rule with id {} registered", rule.getMetadata().getId()); } else { http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/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 b0d7335..442d14f 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 @@ -137,7 +137,7 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentSe segment.getMetadata().setScope("systemscope"); } // Register only if segment does not exist yet - if (getSegmentDefinition(segment.getMetadata().getId()) == null) { + if (getSegmentDefinition(segment.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setSegmentDefinition(segment); logger.info("Predefined segment with id {} registered", segment.getMetadata().getId()); } else { @@ -164,7 +164,7 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentSe scoring.getMetadata().setScope("systemscope"); } // Register only if scoring plan does not exist yet - if (getScoringDefinition(scoring.getMetadata().getId()) == null) { + if (getScoringDefinition(scoring.getMetadata().getId()) == null || bundleContext.getBundle().getVersion().toString().contains("SNAPSHOT")) { setScoringDefinition(scoring); logger.info("Predefined scoring with id {} registered", scoring.getMetadata().getId()); } else { http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/DeployDefinition.java ---------------------------------------------------------------------- diff --git a/tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/DeployDefinition.java b/tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/DeployDefinition.java new file mode 100644 index 0000000..abde5ae --- /dev/null +++ b/tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/DeployDefinition.java @@ -0,0 +1,183 @@ +/* + * 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.shell.commands; + +import org.apache.commons.lang3.StringUtils; +import org.apache.felix.service.command.CommandSession; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.unomi.api.Persona; +import org.apache.unomi.api.PersonaWithSessions; +import org.apache.unomi.api.PropertyType; +import org.apache.unomi.api.actions.ActionType; +import org.apache.unomi.api.campaigns.Campaign; +import org.apache.unomi.api.conditions.ConditionType; +import org.apache.unomi.api.goals.Goal; +import org.apache.unomi.api.rules.Rule; +import org.apache.unomi.api.segments.Scoring; +import org.apache.unomi.api.segments.Segment; +import org.apache.unomi.api.services.*; +import org.apache.unomi.persistence.spi.CustomObjectMapper; +import org.jline.reader.LineReader; +import org.osgi.framework.Bundle; + +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; + +@Command(scope = "unomi", name = "deploy-definition", description = "This will deploy a specific definition") +public class DeployDefinition extends OsgiCommandSupport { + + private DefinitionsService definitionsService; + private GoalsService goalsService; + private ProfileService profileService; + private RulesService rulesService; + private SegmentService segmentService; + + private List<String> definitionTypes = Arrays.asList("condition", "action", "goal", "campaign", "persona", "persona with sessions", "property", "rule", "segment", "scoring"); + + @Argument(index = 0, name = "bundleId", description = "The bundle identifier where to find the definition", required = true, multiValued = false) + Long bundleIdentifier; + + @Argument(index = 1, name = "fileName", description = "The name of the file which contains the definition", required = true, multiValued = false) + String fileName; + + protected Object doExecute() throws Exception { + Bundle bundleToUpdate = bundleContext.getBundle(bundleIdentifier); + if (bundleToUpdate == null) { + System.out.println("Couldn't find a bundle with id: " + bundleIdentifier); + return null; + } + + String definitionTypeAnswer = askUserWithAuthorizedAnswer(session,"Which kind of definition do you want to load?" + getDefinitionTypesWithNumber(), Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10")); + String definitionType = definitionTypes.get(new Integer(definitionTypeAnswer)); + + String path = "META-INF/cxs/" + definitionType; + Enumeration<URL> definitions = bundleToUpdate.findEntries(path, "*.json", true); + if (definitions == null) { + System.out.println("Couldn't find definitions in bundle with id: " + bundleIdentifier + " and definition path: " + path); + return null; + } + + while (definitions.hasMoreElements()) { + URL definitionURL = definitions.nextElement(); + if (definitionURL.toString().contains(fileName)) { + System.out.println("Found definition at " + definitionURL + ", loading... "); + + updateDefinition(definitionType, definitionURL); + } + } + + return null; + } + + private String askUserWithAuthorizedAnswer(CommandSession session, String msg, List<String> authorizedAnswer) throws IOException { + String answer; + do { + answer = promptMessageToUser(session,msg); + } while (!authorizedAnswer.contains(answer.toLowerCase())); + return answer; + } + + private String promptMessageToUser(CommandSession session, String msg) throws IOException { + LineReader reader = (LineReader) session.get(".jline.reader"); + return reader.readLine(msg, null); + } + + private String getDefinitionTypesWithNumber() { + StringBuilder definitionTypesWithNumber = new StringBuilder(); + for (int i = 0; i < definitionTypes.size(); i++) { + definitionTypesWithNumber.append("\n").append(i + 1).append(". ").append(definitionTypes.get(i)); + } + return definitionTypesWithNumber.toString(); + } + + private void updateDefinition(String definitionType, URL definitionURL) { + try { + switch (definitionType) { + case "condition": + ConditionType conditionType = CustomObjectMapper.getObjectMapper().readValue(definitionURL, ConditionType.class); + definitionsService.setConditionType(conditionType); + break; + case "action": + ActionType actionType = CustomObjectMapper.getObjectMapper().readValue(definitionURL, ActionType.class); + definitionsService.setActionType(actionType); + break; + case "goal": + Goal goal = CustomObjectMapper.getObjectMapper().readValue(definitionURL, Goal.class); + goalsService.setGoal(goal); + break; + case "campaign": + Campaign campaign = CustomObjectMapper.getObjectMapper().readValue(definitionURL, Campaign.class); + goalsService.setCampaign(campaign); + break; + case "persona": + Persona persona = CustomObjectMapper.getObjectMapper().readValue(definitionURL, Persona.class); + profileService.savePersona(persona); + break; + case "persona with session": + PersonaWithSessions personaWithSessions = CustomObjectMapper.getObjectMapper().readValue(definitionURL, PersonaWithSessions.class); + profileService.savePersonaWithSessions(personaWithSessions); + break; + case "property": + PropertyType propertyType = CustomObjectMapper.getObjectMapper().readValue(definitionURL, PropertyType.class); + profileService.setPropertyTypeTarget(definitionURL, propertyType); + profileService.setPropertyType(propertyType); + break; + case "rule": + Rule rule = CustomObjectMapper.getObjectMapper().readValue(definitionURL, Rule.class); + rulesService.setRule(rule); + break; + case "segment": + Segment segment = CustomObjectMapper.getObjectMapper().readValue(definitionURL, Segment.class); + segmentService.setSegmentDefinition(segment); + break; + case "scoring": + Scoring scoring = CustomObjectMapper.getObjectMapper().readValue(definitionURL, Scoring.class); + segmentService.setScoringDefinition(scoring); + break; + } + System.out.println("Predefined definition registered"); + } catch (IOException e) { + System.out.println("Error while saving definition " + definitionURL); + System.out.println(e.getMessage()); + } + } + + public void setDefinitionsService(DefinitionsService definitionsService) { + this.definitionsService = definitionsService; + } + + public void setGoalsService(GoalsService goalsService) { + this.goalsService = goalsService; + } + + public void setProfileService(ProfileService profileService) { + this.profileService = profileService; + } + + public void setRulesService(RulesService rulesService) { + this.rulesService = rulesService; + } + + public void setSegmentService(SegmentService segmentService) { + this.segmentService = segmentService; + } +} http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/510c524b/tools/shell-dev-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml ---------------------------------------------------------------------- diff --git a/tools/shell-dev-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/tools/shell-dev-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml index fb1ea70..c86d45f 100644 --- a/tools/shell-dev-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/tools/shell-dev-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -22,9 +22,9 @@ xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:shell="http://karaf.apache.org/xmlns/shell/v1.1.0" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd - http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd - http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd - http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd"> + http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd + http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd + http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd"> <reference id="segmentService" interface="org.apache.unomi.api.services.SegmentService"/> <reference id="userListService" interface="org.apache.unomi.api.services.UserListService"/> @@ -72,6 +72,15 @@ <shell:property name="segmentService" ref="segmentService" /> </shell:action> </shell:command> + <shell:command> + <shell:action class="org.apache.unomi.shell.commands.DeployDefinition"> + <shell:property name="definitionsService" ref="definitionsService" /> + <shell:property name="goalsService" ref="goalsService" /> + <shell:property name="profileService" ref="profileService" /> + <shell:property name="rulesService" ref="rulesService" /> + <shell:property name="segmentService" ref="segmentService" /> + </shell:action> + </shell:command> </shell:command-bundle> </blueprint>
