/*
* Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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.
*/
package org.wso2.carbon.billing.mgt.handlers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.billing.core.BillingEngineContext;
import org.wso2.carbon.billing.core.BillingException;
import org.wso2.carbon.billing.core.BillingHandler;
import org.wso2.carbon.billing.core.dataobjects.Customer;
import org.wso2.carbon.billing.core.dataobjects.Item;
import org.wso2.carbon.billing.core.dataobjects.Subscription;
import org.wso2.carbon.billing.core.jdbc.DataAccessObject;
import org.wso2.carbon.billing.core.scheduler.SchedulerContext;
import org.wso2.carbon.billing.core.utilities.CustomerUtils;
import org.wso2.carbon.billing.mgt.api.MultitenancyBillingInfo;
import org.wso2.carbon.billing.mgt.dataobjects.MultitenancyCustomer;
import org.wso2.carbon.billing.mgt.dataobjects.MultitenancyPackage;
import org.wso2.carbon.billing.mgt.util.Util;
import org.wso2.carbon.common.util.CommonUtil;
import org.wso2.carbon.usage.beans.TenantUsage;
import java.util.*;
public class MultitenancySubscriptionFeedingHandler implements BillingHandler {
private static final Log log = LogFactory.getLog(MultitenancySubscriptionFeedingHandler.class);
private Map<Integer, MultitenancyPackage> multitenancyPackagesMap =
new HashMap<Integer, MultitenancyPackage>();
public void init(Map<String, String> handlerConfig) throws BillingException {
DataAccessObject dataAccessObject = Util.getBillingManager().getDataAccessObject();
MultitenancyBillingInfo billingInfo = Util.getMultitenancyBillingInfo();
// here we are initializing the packages
List<MultitenancyPackage> multitenancyPackages = billingInfo.getMultitenancyPackages();
boolean succeeded = false;
try {
dataAccessObject.beginTransaction();
for (MultitenancyPackage multitenancyPackage : multitenancyPackages) {
// check the package existence in the database; If not available, insert it
int itemId = dataAccessObject.getItemIdWithName(multitenancyPackage.getName());
if (itemId == DataAccessObject.INVALID) {
itemId = dataAccessObject.addItem(multitenancyPackage);
}
multitenancyPackage.setId(itemId);
multitenancyPackagesMap.put(itemId, multitenancyPackage);
// and add all the sub items too
for (Item subItem : multitenancyPackage.getChildren()) {
int subItemId = dataAccessObject.getItemId(subItem.getName(), itemId);
if (subItemId == DataAccessObject.INVALID) {
subItemId = dataAccessObject.addItem(subItem);
}
subItem.setId(subItemId);
}
}
succeeded = true;
}catch (Exception e){
log.error(e.getMessage());
throw new BillingException(e.getMessage(), e);
}finally {
if (succeeded) {
dataAccessObject.commitTransaction();
} else {
dataAccessObject.rollbackTransaction();
}
}
}
public void execute(BillingEngineContext handlerContext) throws BillingException {
feedSubscriptions(handlerContext);
}
private void feedSubscriptions(BillingEngineContext handlerContext) throws BillingException {
// get the subscriptions of the customer.
String filter = handlerContext.getTaskConfiguration().getSubscriptionFilter();
Customer customer = handlerContext.getCustomer();
List<Subscription> subscriptions = getSubscriptions(filter, customer);
log.debug("Found subscriptions: " + subscriptions.size());
//Filtering out the subscription entries of customers who has not activated their accounts
//This will avoid an invoice being generated for such customers
Date endDate;
SchedulerContext schedularContext = handlerContext.getSchedulerContext();
if(schedularContext!=null && schedularContext.getCurrentDurationEnd()!=-1){
endDate = new Date(schedularContext.getCurrentDurationEnd());
}else{
endDate = new Date();
}
Iterator iterator = subscriptions.iterator();
while(iterator.hasNext()){
Subscription subscription = (Subscription) iterator.next();
if(!subscription.isActive() && subscription.getActiveUntil().after(endDate)){
iterator.remove();
}
}
// prepare the handler context
log.debug("Adding subscriptions to the handler context: " + subscriptions.size());
handlerContext.setSubscriptions(subscriptions);
// resetting the single customer back from the fed data
if (customer != null && subscriptions != null && subscriptions.size() != 0) {
Subscription subscription = subscriptions.get(0);
handlerContext.setCustomer(subscription.getCustomer());
}
}
private Item getItem(int itemId) {
return new MultitenancyPackage(multitenancyPackagesMap.get(itemId));
}
private Customer getCustomer(int customerId) throws BillingException {
MultitenancyCustomer customer = new MultitenancyCustomer();
CustomerUtils.fillCustomerData(customerId, customer);
customer.setTenantId(customerId);
//fillTenantUsage(customer);
return customer;
}
private void fillTenantUsage(MultitenancyCustomer customer) throws BillingException {
// first get the current month string
Calendar calendar = Calendar.getInstance();
String monthString = CommonUtil.getMonthString(calendar);
try {
int tenantId = customer.getTenantId();
TenantUsage usage =
Util.getTenantUsageRetriever().getTenantUsage(tenantId, monthString);
long currentDataCapacity = usage.getRegistryContentCapacity();
long historyDataCapacity = usage.getRegistryContentHistoryCapacity();
customer.setCurrentStorage(currentDataCapacity);
customer.setHistoryStorage(historyDataCapacity);
customer.setTotalStorage(currentDataCapacity + historyDataCapacity);
long incomingBW = usage.getTotalIncomingBandwidth();
long outgoingBW = usage.getTotalOutgoingBandwidth();
customer.setIncomingBandwidth(incomingBW);
customer.setOutgoingBandwidth(outgoingBW);
customer.setTotalBandwidth(incomingBW + outgoingBW);
customer.setNumberOfUsers(usage.getNumberOfUsers());
} catch (Exception e) {
String msg = "Error in getting the tenant usage for customer name: "
+ customer.getName() + ".";
log.error(msg);
throw new BillingException(msg, e);
}
}
private List<Subscription> getSubscriptions(String filter,
Customer customer)throws BillingException {
DataAccessObject dataAccessObject = Util.getBillingManager().getDataAccessObject();
List<Subscription> subscriptions = null;
boolean succeeded = false;
Map<Integer, Customer> customersCash = new HashMap<Integer, Customer>();
try {
dataAccessObject.beginTransaction();
if (customer == null) {
subscriptions = dataAccessObject.getFilteredActiveSubscriptions(filter);
} else {
subscriptions = dataAccessObject.getFilteredActiveSubscriptionsForCustomer(filter, customer);
}
if(subscriptions!=null && subscriptions.size()>0){
for (Subscription subscription : subscriptions) {
Customer dummyCustomer = subscription.getCustomer();
int customerId = dummyCustomer.getId();
Customer correctCustomer = customersCash.get(customerId);
if (correctCustomer == null) {
correctCustomer = getCustomer(customerId);
customersCash.put(customerId, correctCustomer);
}
subscription.setCustomer(correctCustomer);
Item dummyItem = subscription.getItem();
Item correctItem = getItem(dummyItem.getId());
subscription.setItem(correctItem);
}
//succeeded = true; //i think it is wrong to place this boolean here. If there are no subscriptions
//this makes the transaction to rollback and hence failing to show the invoice
}
succeeded = true;
}catch (Exception e){
String msg = "Error occurred while getting subscription: " + filter;
if(customer != null) {
msg = msg + " for customer: " + customer.getName();
}
log.error(msg);
throw new BillingException(msg, e);
}finally {
if (succeeded) {
dataAccessObject.commitTransaction();
} else {
dataAccessObject.rollbackTransaction();
}
}
return subscriptions;
}
}