net.cbtltd.server.LicenseService.java Source code

Java tutorial

Introduction

Here is the source code for net.cbtltd.server.LicenseService.java

Source

/**
 * @author   bookingnet
 * @
 * @version   4.0.0
 */
package net.cbtltd.server;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import net.cbtltd.server.api.EventMapper;
import net.cbtltd.server.api.IsService;
import net.cbtltd.server.api.JournalMapper;
import net.cbtltd.server.api.LicenseMapper;
import net.cbtltd.server.api.ProductMapper;
import net.cbtltd.shared.Account;
import net.cbtltd.shared.Balance;
import net.cbtltd.shared.Currency;
import net.cbtltd.shared.Currencyrate;
import net.cbtltd.shared.Data;
import net.cbtltd.shared.Error;
import net.cbtltd.shared.Event;
import net.cbtltd.shared.Journal;
import net.cbtltd.shared.License;
import net.cbtltd.shared.License.Type;
import net.cbtltd.shared.NameId;
import net.cbtltd.shared.Party;
import net.cbtltd.shared.Product;
import net.cbtltd.shared.Serial;
import net.cbtltd.shared.Table;
import net.cbtltd.shared.Unit;
import net.cbtltd.shared.api.HasUrls;
import net.cbtltd.shared.license.LicenseCreate;
import net.cbtltd.shared.license.LicenseDelete;
import net.cbtltd.shared.license.LicenseRead;
import net.cbtltd.shared.license.LicenseTable;
import net.cbtltd.shared.license.LicenseUpdate;

import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;

/** The Class LicenseService performs period license procedures. */
public class LicenseService implements IsService {

    private static final Logger LOG = Logger.getLogger(LicenseService.class.getName());
    private static final HashMap<String, Integer> LICENSED = new HashMap<String, Integer>();
    private static final HashMap<String, Long> ACCESS = new HashMap<String, Long>();
    private static LicenseService service;

    /**
     * Gets the single instance of LicenseService.
     *
     * @return single instance of LicenseService
     */
    public static synchronized LicenseService getInstance() {
        if (service == null) {
            service = new LicenseService();
        }
        return service;
    }

    public static void setAccess(String downstreamid, Long lastaccess) {
        ACCESS.put(downstreamid, lastaccess);
    }

    public static final void checkAccess(SqlSession sqlSession, String upstreamid, String downstreamid,
            String productid, License.Type type, Integer licensewait) {

        //      if (downstreamid == null) {throw new ServiceException(Error.license_bad, downstreamid);}

        licensewait = getLicenseWait(sqlSession, upstreamid, downstreamid, productid, type, licensewait);
        if (licensewait == Integer.MAX_VALUE) {
            throw new ServiceException(Error.license_absent, downstreamid + " " + productid);
        }
        Long now = System.currentTimeMillis();
        Long lastaccess = ACCESS.get(downstreamid);
        //////////Commneted out for XML test No Production ////////////////////
        //if (lastaccess != null && (lastaccess + licensewait) > now) {throw new ServiceException(Error.license_wait, String.valueOf(licensewait) + "ms");}
        ///////Commneted out for XML test No Production ////////////////////
        LOG.debug("checkAccess " + String.valueOf(lastaccess) + " " + String.valueOf(licensewait) + " "
                + String.valueOf(now));
    }

    /**
     * Executes the LicenseCreate action.
     *
     * @param sqlSession the current SQL session
     * @param action the action to be executed.
     * @return the response.
     */
    public final License execute(SqlSession sqlSession, LicenseCreate action) {
        LOG.debug("LicenseCreate in " + action);
        try {
            sqlSession.getMapper(LicenseMapper.class).create(action);
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        }
        return action;
    }

    /**
     * Executes the LicenseRead action.
     *
     * @param sqlSession the current SQL session
     * @param action the action to be executed.
     * @return the response.
     */
    public final License execute(SqlSession sqlSession, LicenseRead action) {
        License license = null;
        try {
            license = sqlSession.getMapper(LicenseMapper.class).read(action.getId());
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        }
        return license;
    }

    /**
     * Executes the LicenseUpdate action.
     *
     * @param sqlSession the current SQL session
     * @param action the action to be executed.
     * @return the response.
     */
    public final License execute(SqlSession sqlSession, LicenseUpdate action) {
        LOG.debug("LicenseUpdate " + action);
        try {
            sqlSession.getMapper(LicenseMapper.class).update(action);
            MonitorService.update(sqlSession, Data.Origin.CONSOLE, NameId.Type.License, action);
            LICENSED.clear();
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        }
        return action;
    }

    /**
     * Executes the LicenseDelete action.
     *
     * @param sqlSession the current SQL session
     * @param action the action to be executed.
     * @return the response.
     */
    public final License execute(SqlSession sqlSession, LicenseDelete action) {
        try {
            sqlSession.getMapper(LicenseMapper.class).delete(action.getId());
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        }
        return null;
    }

    /**
     * Executes the LicenseTable action to read an license table for a property.
     *
     * @param sqlSession the current SQL session.
     * @param action the action to be executed.
     * @return the response.
     */
    public final Table<License> execute(SqlSession sqlSession, LicenseTable action) {
        LOG.debug("LicenseTable in " + action);
        Table<License> table = new Table<License>();
        try {
            table.setDatasize(sqlSession.getMapper(LicenseMapper.class).count(action));
            table.setValue(sqlSession.getMapper(LicenseMapper.class).list(action));
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        }
        LOG.debug("LicenseTable out " + table);
        return table;
    }

    /**
     * Gets the array of licensed product IDs from the supplied list.
     *
     * @param sqlSession the current SQL session.
     * @param upstreamid the ID of the product supplier.
     * @param downstreamid the ID of the product consumer
     * @param productids the ID of the product.
     * @param type the type of license.
     * @param date the date to be checked.
     * @return the array of licensed product IDs.
     */
    public static final ArrayList<String> getLicensed(SqlSession sqlSession, String upstreamid, String downstreamid,
            ArrayList<String> productids, License.Type type, Integer licensewait) {
        ArrayList<String> licensed = new ArrayList<String>();
        for (String productid : productids) {
            if (isLicensed(sqlSession, upstreamid, downstreamid, productid, type, licensewait)) {
                licensed.add(productid);
            }
        }
        return licensed;
    }

    /**
     * Checks if the product is licensed.
     *
     * @param sqlSession the current SQL session.
     * @param upstreamid the ID of the product supplier.
     * @param downstreamid the ID of the product consumer
     * @param productids the ID of the product.
     * @param type the type of license.
     * @param date the date to be checked.
     * @return true, if licensed
     */
    public static final Integer getLicenseWait(SqlSession sqlSession, String upstreamid, String downstreamid,
            String productid, License.Type type, Integer licensewait) {

        //      Integer licensewait = License.DEFAULT_WAIT;
        try {
            if (type == null || License.Type.All == type || License.Type.None == type) {
                throw new ServiceException(Error.license_type, type.name());
            }

            if (upstreamid == null && productid != null) {
                Product product = sqlSession.getMapper(ProductMapper.class).read(productid);
                upstreamid = product == null ? null : product.getSupplierid();
            }

            //         if (downstreamid == null && upstreamid == null) {return License.DEFAULT_WAIT;} // no product
            if (downstreamid != null && upstreamid != null && downstreamid.equalsIgnoreCase(upstreamid)) {
                return licensewait;
            } // agent is manager

            License action = new License(upstreamid, downstreamid, productid, type, licensewait, new Date());
            String key = action.getKey();
            if (LICENSED.containsKey(key)) {
                return LICENSED.get(key);
            }
            licensewait = getLicenseWait(sqlSession, action);
            LICENSED.put(key, licensewait);
            LOG.debug("LICENSED " + key + " " + licensewait + " " + LICENSED.size());
        } catch (Throwable x) {
            x.printStackTrace();
        }
        return licensewait;
    }

    public static final boolean isLicensed(SqlSession sqlSession, String upstreamid, String downstreamid,
            String productid, License.Type type, Integer licensewait) {
        return getLicenseWait(sqlSession, upstreamid, downstreamid, productid, type,
                licensewait) != Integer.MAX_VALUE;
    }

    /**
     * Checks if product is licensed and returns response wait in milliseconds.
     *
     * @param sqlSession the current SQL session.
     * @param action the license parameter.
     * @return response wait in milliseconds.
     */
    private static final Integer getLicenseWait(SqlSession sqlSession, License action) {

        License exists = sqlSession.getMapper(LicenseMapper.class).exists(action);
        if (exists != null) {
            return exists.getWait();
        }

        String type = action.getType();
        action.setType(null);
        exists = sqlSession.getMapper(LicenseMapper.class).exists(action);
        if (exists != null) {
            return exists.notType(Type.None) ? exists.getWait() : Integer.MAX_VALUE;
        }

        action.setProductid(null);
        action.setType(type);
        exists = sqlSession.getMapper(LicenseMapper.class).exists(action);
        if (exists != null) {
            return exists.getWait();
        }

        action.setType(null);
        exists = sqlSession.getMapper(LicenseMapper.class).exists(action);
        if (exists != null) {
            return exists.notType(Type.None) ? exists.getWait() : Integer.MAX_VALUE;
        }

        action.setDownstreamid(null);
        action.setType(type);
        exists = sqlSession.getMapper(LicenseMapper.class).exists(action);
        if (exists != null) {
            return exists.getWait();
        }

        action.setType(null);
        exists = sqlSession.getMapper(LicenseMapper.class).exists(action);
        if (exists != null) {
            return exists.notType(Type.None) ? exists.getWait() : Integer.MAX_VALUE;
        }

        return action.getWait();
    }

    /**
     * Service to check if license fees and commission are paid and reinstate if OK.
     *
     * @param partyid the ID of the party to be checked.
     */
    public static void check(SqlSession sqlSession, String partyid) {
        Balance balance = sqlSession.getMapper(JournalMapper.class)
                .licensebalance(new NameId(Party.CBT_LTD_PARTY, partyid));
        if (balance != null && balance.getBalance() >= 0.0) {
            sqlSession.getMapper(ProductMapper.class).restoreparty(partyid);
        }
    }

    /**
     * Service to calculate license fees and commission at the end of each month.
     *
     * @param date of license run.
     */
    public static void license(Date date) {
        LOG.debug("License run at " + date);
        SqlSession sqlSession = RazorServer.openSession();
        try {
            ArrayList<Balance> openingbalances = sqlSession.getMapper(JournalMapper.class)
                    .licensebalances(Party.CBT_LTD_PARTY);

            {
                ArrayList<Journal> journals = sqlSession.getMapper(JournalMapper.class).license(date);
                Event<Journal> event = null;
                String thisOrganizationid = null;

                int i = 0;
                for (Journal journal : journals) {
                    if (!journal.hasOrganizationid(thisOrganizationid)) {
                        i++;
                        endEvent(sqlSession, event, "License Total");
                        thisOrganizationid = journal.getOrganizationid();
                        event = createEvent(sqlSession, thisOrganizationid, date, "License");
                    }
                    event.addItem(journal);
                }
                endEvent(sqlSession, event, "License Total");
            }
            {
                ArrayList<Journal> journals = sqlSession.getMapper(JournalMapper.class).commission(date);
                Event<Journal> event = null;
                String thisOrganizationid = null;

                for (Journal journal : journals) {
                    if (!journal.hasOrganizationid(thisOrganizationid)) {
                        endEvent(sqlSession, event, "Commission Total");
                        thisOrganizationid = journal.getOrganizationid();
                        event = createEvent(sqlSession, thisOrganizationid, date, "Commission");
                    }
                    journal.setDebitamount(journal.getDebitamount() * WebService.getRate(sqlSession,
                            journal.getCurrency(), Currency.Code.USD.name(), event.getDate()));
                    journal.setCurrency(Currency.Code.USD.name());
                    event.addItem(journal);
                }
                endEvent(sqlSession, event, "Commission Total");
            }

            LOG.debug("License openingbalances " + openingbalances);
            suspend(sqlSession, date, openingbalances);
            sqlSession.commit();
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        } finally {
            sqlSession.close();
        }
    }

    /*
     * Creates a new license invoice journal event.
     * 
     * @param sqlSession the current SQL session.
     * @param organizationid the ID of the organization being invoiced.
     * @param date the effective date of the invoice.
     * @param notes the descriptive text of the invoice.
     * @return the license invoice journal event.
     */
    private static Event<Journal> createEvent(SqlSession sqlSession, String organizationid, Date date,
            String notes) {
        DateFormat df = new SimpleDateFormat("MMMMM yyyy");
        Event<Journal> event = new Event<Journal>();
        event.setOrganizationid(organizationid);
        event.setActorid(Party.NO_ACTOR);
        event.setDate(date);
        event.setDuedate(date);
        event.setProcess(Event.Type.Purchase.name());
        event.setType(Event.ACCOUNTING);
        event.setNotes(notes + " for " + df.format(date));
        Date firstlicensedate = sqlSession.getMapper(JournalMapper.class).firstlicensedate(organizationid);
        if (firstlicensedate == null || date.before(firstlicensedate)) {
            event.setState(Event.FINAL);
        } else {
            event.setState(Event.CREATED);
        }
        return event;
    }

    /*
     * Creates the line items of a license invoice journal event.
     * 
     * @param sqlSession the current SQL session.
     * @param event the invoice journal event.
     * @param description the descriptive text of the line item.
     */
    private static void endEvent(SqlSession sqlSession, Event<Journal> event, String description) {
        LOG.debug("License endEvent " + event);
        if (event == null || event.noItems()) {
            return;
        }
        Double balance = 0.0;
        for (Journal item : event.getItems()) {
            balance += item.getDebitamount();
        }
        if (Math.abs(balance) < 0.01) {
            return;
        }

        Journal journal = new Journal();
        journal.setEntitytype(NameId.Type.Party.name());
        journal.setEntityid(Party.CBT_LTD_PARTY);
        journal.setAccountid(Account.ACCOUNTS_PAYABLE);
        journal.setCreditamount(balance);
        journal.setDebitamount(0.0);
        journal.setDescription(description);
        journal.setEventid(event.getId());
        journal.setOrganizationid(event.getOrganizationid());
        journal.setQuantity(1.0);
        journal.setUnit(Unit.MON);
        journal.setCurrency(Currency.Code.USD.name());
        event.addItem(journal);

        event.setName(SessionService.pop(sqlSession, event.getOrganizationid(), Serial.JOURNAL));
        sqlSession.getMapper(EventMapper.class).create(event);
        for (Journal item : event.getItems()) {
            item.setEventid(event.getId());
            sqlSession.getMapper(JournalMapper.class).create(item);
        }
    }

    /*
     * Suspends accounts whose balances exceed a threshold.
     *
     * @param sqlSession the current SQL session.
     * @param balances to be evaluated for suspension.
     */
    private static final void suspend(SqlSession sqlSession, Date date, ArrayList<Balance> balances) {

        //      Report report = new Report();
        //      report.setActorid(Party.ADMINISTRATOR);
        //      report.setCurrency(Currency.Code.USD.name());
        //      report.setDate(new Date());
        //      report.setDesign(Design.LICENSE_SALE);
        //      report.setFormat(Report.PDF);
        //      report.setNotes("Automatically generated by License Service");
        //      report.setFromdate(date);
        //      report.setTodate(date);

        for (Balance balance : balances) {

            //         report.setOrganizationid(balance.getPartyid());
            //         report = ReportService.execute(sqlSession, report);

            Currencyrate currencyrate = new Currencyrate(balance.getCurrency(), Currency.Code.USD.name(),
                    new Date());
            currencyrate.setRate(WebService.getRate(sqlSession, currencyrate));
            boolean suspended = balance.getBalance() >= 100.0; //Allow margin
            if (suspended) {
                sqlSession.getMapper(ProductMapper.class).suspendparty(balance.getPartyid());
                EmailService.licensesuspended(balance.getEmailaddress(), balance.getBalance(), currencyrate);
            } else {
                EmailService.licenseinvoiced(balance.getEmailaddress(), balance.getBalance(), currencyrate);
            }
        }
    }

    /** Service to calculate license fees and commission balances and email addresses. */
    public static final void balance() {
        SqlSession sqlSession = RazorServer.openSession();
        try {
            //         Report report = new Report();
            //         report.setActorid(Party.ADMINISTRATOR);
            //         report.setCurrency(Currency.Code.USD.name());
            //         report.setDate(new Date());
            //         report.setDesign(Design.LICENSE_STATEMENT);
            //         report.setFormat(Report.PDF);
            //         report.setNotes("Automatically generated by License Service");
            //         report.setTodate(new Date());

            ArrayList<Balance> balances = sqlSession.getMapper(JournalMapper.class)
                    .licensebalances(Party.CBT_LTD_PARTY);
            LOG.debug("balance " + balances);
            for (Balance balance : balances) {

                //            report.setOrganizationid(balance.getPartyid());
                //            report = ReportService.execute(sqlSession, report);

                Currencyrate currencyrate = new Currencyrate(balance.getCurrency(), Currency.Code.USD.name(),
                        new Date());
                currencyrate.setRate(WebService.getRate(sqlSession, currencyrate));
                EmailService.licensebalance(balance.getEmailaddress(), balance.getBalance(), currencyrate);
            }
        } catch (Throwable x) {
            sqlSession.rollback();
            MonitorService.log(x);
        } finally {
            sqlSession.close();
        }
    }
}