/* jBilling - The Enterprise Open Source Billing System Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde This file is part of jbilling. jbilling is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. jbilling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with jbilling. If not, see <http://www.gnu.org/licenses/>. */ package com.sapienter.jbilling.server.provisioning.task; import java.math.BigDecimal; import java.util.Date; import java.util.LinkedList; import java.util.List; import javax.jms.JMSException; import org.apache.log4j.Logger; import org.drools.KnowledgeBase; import com.sapienter.jbilling.server.order.db.OrderDAS; import com.sapienter.jbilling.server.order.db.OrderDTO; import com.sapienter.jbilling.server.order.db.OrderLineDTO; import com.sapienter.jbilling.server.order.event.NewQuantityEvent; import com.sapienter.jbilling.server.pluggableTask.PluggableTask; import com.sapienter.jbilling.server.pluggableTask.TaskException; import com.sapienter.jbilling.server.pluggableTask.admin.PluggableTaskException; import com.sapienter.jbilling.server.provisioning.event.SubscriptionActiveEvent; import com.sapienter.jbilling.server.provisioning.event.SubscriptionInactiveEvent; import com.sapienter.jbilling.server.system.event.Event; import com.sapienter.jbilling.server.system.event.task.IInternalEventsTask; import com.sapienter.jbilling.server.util.Constants; import java.util.ArrayList; /** * @author othman * */ public class ProvisioningCommandsRulesTask extends PluggableTask implements IInternalEventsTask { private static final Logger LOG = Logger.getLogger(ProvisioningCommandsRulesTask.class); public static final String ACTIVATED_EVENT_TYPE = "activated"; public static final String DEACTIVATED_EVENT_TYPE = "deactivated"; @SuppressWarnings("unchecked") private static final Class<Event> events[] = new Class[] { SubscriptionActiveEvent.class, SubscriptionInactiveEvent.class, NewQuantityEvent.class }; public Class<Event>[] getSubscribedEvents() { return events; } /* * (non-Javadoc) * * @see * com.sapienter.jbilling.server.system.event.task.IInternalEventsTask#process(com.sapienter.jbilling.server.system.event.Event) */ public void process(Event event) throws PluggableTaskException { try { // the order and the order lines have to be visible to the rules KnowledgeBase knowledgeBase; try { knowledgeBase = readKnowledgeBase(); } catch (Exception e) { throw new TaskException(e); } session = knowledgeBase.newStatefulKnowledgeSession(); if (event instanceof SubscriptionActiveEvent) { SubscriptionActiveEvent active = (SubscriptionActiveEvent) event; LOG.debug("The order " + active.getOrder().getId() + " is active "); processRules(active.getOrder(), ACTIVATED_EVENT_TYPE); } else if (event instanceof SubscriptionInactiveEvent) { SubscriptionInactiveEvent inactive = (SubscriptionInactiveEvent) event; LOG.debug("The order " + inactive.getOrder().getId() + " is inactive"); processRules(inactive.getOrder(), DEACTIVATED_EVENT_TYPE); } else if (event instanceof NewQuantityEvent) { NewQuantityEvent newQuantity = (NewQuantityEvent) event; if (BigDecimal.ZERO.compareTo(newQuantity.getOldQuantity()) != 0 && BigDecimal.ZERO.compareTo(newQuantity.getNewQuantity()) != 0) { return; } Integer orderId = newQuantity.getOrderId(); OrderDAS orderDb = new OrderDAS(); OrderDTO order = orderDb.find(orderId); if ((order == null) || !checkOrder(order)) { return; } String typeEvent = ""; if (BigDecimal.ZERO.compareTo(newQuantity.getOldQuantity()) == 0) { typeEvent = ACTIVATED_EVENT_TYPE; } if (BigDecimal.ZERO.compareTo(newQuantity.getNewQuantity()) == 0) { typeEvent = DEACTIVATED_EVENT_TYPE; } LOG.debug("NewQuantityEvent order line " + newQuantity.getOrderLine().getId() + " is " + typeEvent); processRules(order, newQuantity.getOrderLine(), typeEvent); } else { throw new PluggableTaskException("Cant not process event " + event); } } catch (TaskException e) { throw new PluggableTaskException(e); } } /** * @param newOrder * @param eventType * @throws TaskException */ protected void processRules(OrderDTO newOrder, String eventType) throws TaskException { List<Object> rulesMemoryContext = new ArrayList<Object>(); CommandManager commandManager = new CommandManager(eventType, newOrder); // Add order lines for (OrderLineDTO line : newOrder.getLines()) { rulesMemoryContext.add(line); } // add helper command order rulesMemoryContext.add(commandManager); // then execute the rules for (Object o : rulesMemoryContext) { LOG.debug("in memory context=" + o); } // then execute the rules LOG.debug("execute provisioning Rules."); executeStatefulRules(session, rulesMemoryContext); LOG.debug("execute provisioning Rules Done."); // send commands queue through JMS sendCommandQueue(eventType, commandManager, newOrder); } /** * @param line * @param eventType * @throws TaskException */ protected void processRules(OrderDTO newOrder, OrderLineDTO line, String eventType) throws TaskException { List<Object> rulesMemoryContext = new ArrayList<Object>(); CommandManager commandManager = new CommandManager(eventType, newOrder); rulesMemoryContext.add(line); // add helper command order rulesMemoryContext.add(commandManager); // then execute the rules for (Object o : rulesMemoryContext) { LOG.debug("in memory context=" + o); } // then execute the rules executeStatefulRules(session, rulesMemoryContext); // send commands queue through JMS sendCommandQueue(eventType, commandManager, newOrder); } /** * sends commands queue through JMS * * @param eventType * @throws TaskException */ private void sendCommandQueue(String eventType, CommandManager c, OrderDTO order) throws TaskException { LOG.debug("calling sendCommandQueue()"); try { CommandsQueueSender cmdSender = new CommandsQueueSender(order); cmdSender.postCommandsQueue(c.getCommands(), eventType); } catch (JMSException e) { throw new TaskException(e); } } /** * @param order * @return */ private boolean checkOrder(OrderDTO order) { boolean valid = false; Date today = new Date(); if ((order.getOrderStatus() != null) && (order.getOrderStatus().getId() == Constants.ORDER_STATUS_ACTIVE)) { if (((order.getActiveSince() != null) && order.getActiveSince() .before(today)) && ((order.getActiveUntil() != null) && order .getActiveUntil().after(today))) { valid = true; } } LOG.debug(" checkOrder(): is order valid ? :" + valid); return valid; } /** * Helper class * * @author othman * */ public class CommandManager { private static final String COMMAND_NAME = "command"; private static final String ORDER_LINE_ID = "order_line_id"; /** * */ private static final long serialVersionUID = 1L; private OrderDTO order = null; private LinkedList<LinkedList<StringPair>> commands = new LinkedList<LinkedList<StringPair>>();; private LinkedList<StringPair> commandQueue; private String eventType; /** * @param eventType * @param order */ public CommandManager(String eventType, OrderDTO order) { this.eventType = eventType; this.order = order; } public void addCommand(String command, Integer orderLineId) { LOG.debug("calling CommandManager.addCommand()"); LOG.debug("command=" + command); LOG.debug("orderLineId=" + orderLineId.intValue()); // add current command queue to global queue if (commandQueue != null) { commands.add(commandQueue); LOG.debug("added command queue " + commandQueue); } // create new queue for "command" commandQueue = new LinkedList<StringPair>(); StringPair param = new StringPair(COMMAND_NAME, command); commandQueue.add(param); param = new StringPair(ORDER_LINE_ID, orderLineId.toString()); commandQueue.add(param); LOG.debug("added command : " + command); } public void addParameter(String name, String value) { StringPair param = new StringPair(name, value); commandQueue.add(param); LOG.debug("added command parameter: " + param); } /** * @return the order */ public OrderDTO getOrder() { return order; } /** * @param order * the order to set */ public void setOrder(OrderDTO order) { this.order = order; } /** * @return the eventType */ public String getEventType() { return eventType; } /** * @return the commands */ public LinkedList<LinkedList<StringPair>> getCommands() { // parameters command queue should be added if (commandQueue != null) { commands.add(commandQueue); LOG.debug("added command queue " + commandQueue); } return commands; } } }