Package org.libreplan.business.orders.entities

Source Code of org.libreplan.business.orders.entities.CriterionRequirementHandler

/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
*                         Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program 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.
*
* This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.libreplan.business.orders.entities;

import static org.libreplan.business.i18n.I18nHelper._;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.sql.Template;
import org.libreplan.business.requirements.entities.CriterionRequirement;
import org.libreplan.business.requirements.entities.DirectCriterionRequirement;
import org.libreplan.business.requirements.entities.IndirectCriterionRequirement;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.ResourceEnum;
import org.libreplan.business.templates.entities.OrderElementTemplate;

/**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Diego Pino Garcia <dpino@igalia.com>
*/

// <OrderElement, OrderLine, OrderLineGroup>
public abstract class CriterionRequirementHandler<T, S, R> {

    // Operations to add a criterionRequirement
    public void propagateDirectCriterionRequirementAddition(T orderElement,
            CriterionRequirement directo) {
        propagateIndirectCriterionRequirement(orderElement,
                (DirectCriterionRequirement) directo);
    }

    protected void propagateIndirectCriterionRequirement(T orderElement,
            CriterionRequirement direct) {

        if (isOrderLine(orderElement)) {
            propagateIndirectCriterionRequirementToOrderLineChildren(
                    toOrderLine(orderElement),
                    (DirectCriterionRequirement) direct);
        } else {
            propagateIndirectCriterionRequirementToOrderLineGroupChildren(
                    toOrderLineGroup(orderElement),
                    (DirectCriterionRequirement) direct);
        }
    }

    protected void propagateIndirectCriterionRequirementToOrderLineGroupChildren(
            R orderLineGroup, DirectCriterionRequirement parent) {
        Criterion criterion = parent.getCriterion();
        for (T child : getOrderLineGroupChildren(orderLineGroup)) {
            IndirectCriterionRequirement indirect = IndirectCriterionRequirement
                    .create(parent, criterion);
            addIndirectCriterionRequirement(child, indirect);
            propagateIndirectCriterionRequirement(child, parent);
        }
    }

    protected void propagateIndirectCriterionRequirementToOrderLineChildren(
            S orderLine, DirectCriterionRequirement parent) {
        for (HoursGroup hoursGroup : getHoursGroups(orderLine)) {
            hoursGroup.updateMyCriterionRequirements();
        }
    }

    protected abstract boolean isOrderLine(T orderElement);

    protected abstract S toOrderLine(T orderElement);

    protected abstract R toOrderLineGroup(T orderElement);

    protected abstract List<HoursGroup> getHoursGroups(S orderline);

    protected abstract List<T> getOrderLineGroupChildren(R orderLineGroup);

    public boolean canAddCriterionRequirement(T orderElement,
            CriterionRequirement newRequirement) {
        List<T> listOrderElements = getAllChildren(orderElement);
        listOrderElements.add(orderElement);
        for (T element : listOrderElements) {
            if (existSameCriterionRequirement(element, newRequirement)) {
                return false;
            }
        }
        return true;
    }

    protected abstract List<T> getAllChildren(T orderElement);

    public boolean existSameCriterionRequirement(T orderElement,
            CriterionRequirement newRequirement) {
        if (isOrderLine(orderElement)) {
            return existSameCriterionRequirementIntoOrderLine(toOrderLine(orderElement), newRequirement);
        } else {
            return existSameCriterionRequirementIntoOrderElement(orderElement,
                    newRequirement);
        }
    }

    public boolean existSameCriterionRequirementIntoOrderLine(S orderLine,
            CriterionRequirement newRequirement) {
        if (existSameCriterionRequirementIntoOrderElement(toOrderElement(orderLine),
                newRequirement)) {
            return true;
        }
        for (HoursGroup hoursGroup : getHoursGroups(orderLine)) {
            if (hoursGroup.existSameCriterionRequirement(newRequirement)) {
                return true;
            }
        }
        return false;
    }

    protected abstract T toOrderElement(S orderLine);

    public boolean existSameCriterionRequirementIntoOrderElement(
            T orderElement, CriterionRequirement newRequirement) {
        Criterion criterion = newRequirement.getCriterion();
        for (CriterionRequirement requirement : getCriterionRequirements(orderElement)) {
            if (requirement.getCriterion().equals(criterion)) {
                return true;
            }
        }
        return false;
    }

    protected abstract Set<CriterionRequirement> getCriterionRequirements(
            T orderElement);

    /*
     * Operations to set the valid value of a criterion Requirements and the
     * criterion Requirement of its children.
     */

    public void propagateValidCriterionRequirement(T orderElement,
            DirectCriterionRequirement parent, boolean valid) {
        if (isOrderLine(orderElement)) {
            setValidCriterionRequirementChildrenAsOrderLine(
                    toOrderLine(orderElement), parent, valid);
        } else {
            setValidCriterionRequirementChildrenAsOrderLineGroup(
                    toOrderLineGroup(orderElement), parent, valid);
        }
    }

    protected void setValidCriterionRequirementChildrenAsOrderLineGroup(
            R orderLineGroup, DirectCriterionRequirement parent,
            boolean valid) {
        for (T child : getOrderLineGroupChildren(orderLineGroup)) {
            IndirectCriterionRequirement indirect = findIndirectRequirementByParent(
                    getIndirectCriterionRequirement(child), parent);
            if (indirect != null) {
                indirect.setValid(valid);
            }
            propagateValidCriterionRequirement(child, parent, valid);
        }
    }

    protected abstract Set<IndirectCriterionRequirement> getIndirectCriterionRequirement(
            T orderElement);

    protected void setValidCriterionRequirementChildrenAsOrderLine(S orderLine,
            DirectCriterionRequirement parent, boolean valid) {
        for (HoursGroup hoursGroup : getHoursGroups(orderLine)) {
            IndirectCriterionRequirement indirect = findIndirectRequirementByParent(
                    hoursGroup.getIndirectCriterionRequirement(), parent);
            if (indirect != null) {
                indirect.setValid(valid);
            }
        }
    }

    /*
     * Operation to update the criterions requirements of the orderElement and
     * its children
     */
    public void propagateRemoveCriterionRequirement(T orderElement,
            DirectCriterionRequirement parent) {
        if (isOrderLine(orderElement)) {
            removeIndirectCriterionRequirementAsOrderLine(toOrderLine(orderElement), parent);
        } else {
            removeIndirectCriterionRequirement(toOrderLineGroup(orderElement),
                    parent);
        }
    }

    protected void removeIndirectCriterionRequirement(
            R orderLineGroup, DirectCriterionRequirement parent) {
        for (T child : getOrderLineGroupChildren(orderLineGroup)) {
            IndirectCriterionRequirement indirect = findIndirectRequirementByParent(
                    getIndirectCriterionRequirement(child), parent);
            if (indirect != null) {
                propagateRemoveCriterionRequirement(child, parent);
                removeCriterionRequirement(child, indirect);
            }
        }
    }

    protected abstract void removeCriterionRequirement(T orderElement,
            CriterionRequirement criterionRequirement);

    protected void removeIndirectCriterionRequirementAsOrderLine(S orderLine,
            DirectCriterionRequirement parent) {
        for (HoursGroup hoursGroup : getHoursGroups(orderLine)) {
            IndirectCriterionRequirement indirect = findIndirectRequirementByParent(
                    hoursGroup.getIndirectCriterionRequirement(), parent);
            if (indirect != null) {
                hoursGroup.removeCriterionRequirement(indirect);
            }
        }
    }

    public void removeDirectCriterionRequirement(T orderElement, DirectCriterionRequirement criterionRequirement){
        propagateRemoveCriterionRequirement(orderElement, criterionRequirement);
        removeCriterionRequirement(orderElement, criterionRequirement);
    }

    protected abstract List<HoursGroup> getOrderLineHoursGroups(S orderLine);

    /*
     * Operation to update the criterions requirements of the orderElement and
     * its children
     */

    public void propagateUpdateCriterionRequirements(T orderElement) {
        if (orderElement instanceof OrderLine) {
            updateCriterionRequirementsIntoOrderLine(toOrderLine(orderElement));
        } else {
            updateCriterionRequirementsIntoOrderLineGroup(toOrderLineGroup(orderElement));
        }
    }

    private void updateCriterionRequirementsIntoOrderLineGroup(
            R orderLineGroup) {
        for (T child : getOrderLineGroupChildren(orderLineGroup)) {
            updateMyCriterionRequirements(child);
            propagateUpdateCriterionRequirements(child);
        }
    }

    protected abstract List<T> getChildren(T orderElement);

    public void updateCriterionRequirementsIntoOrderLine(S orderLine) {
        for (HoursGroup hoursGroup : getHoursGroups(orderLine)) {
            hoursGroup.updateMyCriterionRequirements();
        }
    }

    public void propagateIndirectCriterionRequirementsKeepingValid(S orderLine) {
        for (HoursGroup hoursGroup : getHoursGroups(orderLine)) {
            hoursGroup.propagateIndirectCriterionRequirementsKeepingValid();
        }
    }

    void transformDirectToIndirectIfNeeded(T orderElement,
            Set<IndirectCriterionRequirement> currents) {
        for (DirectCriterionRequirement direct : getDirectCriterionRequirement(orderElement)) {
            IndirectCriterionRequirement indirect = findIndirectRequirementByCriterion(
                    currents, direct.getCriterion());
            if (indirect != null) {
                removeDirectCriterionRequirement(orderElement, direct);
            }
        }
    }

    protected abstract Set<DirectCriterionRequirement> getDirectCriterionRequirement(
            T orderElement);

    void addNewsIndirects(T orderElement,
            Set<IndirectCriterionRequirement> currents) {
        Set<IndirectCriterionRequirement> indirects = getIndirectCriterionRequirement(orderElement);
        for (IndirectCriterionRequirement current : currents) {
            if (!indirects.contains(current)) {
                basicAddCriterionRequirement(orderElement, current);
            }
        }
    }

    protected abstract void basicAddCriterionRequirement(T orderElement,
            CriterionRequirement criterionRequirement);

    void removeOldIndirects(T orderElement,
            Set<IndirectCriterionRequirement> currents) {
        for (IndirectCriterionRequirement indirect : getIndirectCriterionRequirement(orderElement)) {
            if (!currents.contains(indirect)) {
                removeCriterionRequirement(orderElement, indirect);
            }
        }
    }

    void transformDirectToIndirectIfNeeded(HoursGroup hoursGroup,
            Set<IndirectCriterionRequirement> currents) {
        for (DirectCriterionRequirement direct : hoursGroup
                .getDirectCriterionRequirement()) {
            IndirectCriterionRequirement indirect = findIndirectRequirementByCriterion(
                    currents, direct.getCriterion());
            if (indirect != null) {
                hoursGroup.removeCriterionRequirement(direct);
            }
        }
    }

    void addNewsIndirects(HoursGroup hoursGroup,
            Set<IndirectCriterionRequirement> currents) {
        Set<IndirectCriterionRequirement> indirects = hoursGroup
                .getIndirectCriterionRequirement();
        for (IndirectCriterionRequirement current : currents) {
            if (!indirects.contains(current)) {
                hoursGroup.addCriterionRequirement(current);
            }
        }
    }

    void removeOldIndirects(HoursGroup hoursGroup,
            Set<IndirectCriterionRequirement> currents) {
        for (IndirectCriterionRequirement indirect : hoursGroup
                .getIndirectCriterionRequirement()) {
            if (!currents.contains(indirect)) {
                hoursGroup.removeCriterionRequirement(indirect);
            }
        }
    }

    Set<IndirectCriterionRequirement> getCurrentIndirectRequirements(
            Set<IndirectCriterionRequirement> oldIndirects,
            Set<CriterionRequirement> requirementsParent) {
        Set<IndirectCriterionRequirement> currentIndirects = new HashSet<IndirectCriterionRequirement>();
        for (CriterionRequirement requirement : requirementsParent) {
            IndirectCriterionRequirement indirect = getCurrentIndirectRequirement(
                    oldIndirects, requirement);
            currentIndirects.add(indirect);
        }
        return currentIndirects;
    }

    IndirectCriterionRequirement getCurrentIndirectRequirement(
            Set<IndirectCriterionRequirement> oldIndirects,
            CriterionRequirement requirement) {

        IndirectCriterionRequirement indirect;
        DirectCriterionRequirement parent;
        boolean valid = true;
        if (requirement instanceof DirectCriterionRequirement) {
            parent = (DirectCriterionRequirement) requirement;
        } else {
            parent = ((IndirectCriterionRequirement) requirement).getParent();
            valid = ((IndirectCriterionRequirement) requirement).isValid();
        }

        indirect = findIndirectRequirementByParent(oldIndirects, parent);
        if (indirect == null) {
            indirect = IndirectCriterionRequirement.create(parent, requirement
                    .getCriterion());
            indirect.setValid(valid);
        }
        return (IndirectCriterionRequirement) indirect;
    }

    private IndirectCriterionRequirement findIndirectRequirementByParent(
            Set<IndirectCriterionRequirement> indirects,
            DirectCriterionRequirement newParent) {

        for (IndirectCriterionRequirement requirement : indirects) {
            if (requirement.getParent().equals(newParent)) {
                return requirement;
            }
        }
        return null;
    }

    private IndirectCriterionRequirement findIndirectRequirementByCriterion(
            Set<IndirectCriterionRequirement> indirects, Criterion criterion) {

        for (IndirectCriterionRequirement requirement : indirects) {
            if (requirement.getCriterion().equals(criterion)) {
                return requirement;
            }
        }
        return null;
    }

    /*
     * Operation to create and add to a orderElement new criterion requirements
     * that it is copied of the criterion requirements of other orderElement
     */
    protected void copyRequirementToOrderLineGroup(S orderLine, R orderLineGroup) {
        // copy the directCriterionRequirement
        for (DirectCriterionRequirement newRequirement :
                copyDirectRequirements(getDirectCriterionRequirementFromOrderLine(orderLine))) {
            basicAddCriterionRequirementIntoOrderLineGroup(orderLineGroup, newRequirement);
        }

        // copy the IndirectCriterionRequirement
        for (IndirectCriterionRequirement newRequirement :
                copyIndirectRequirements(getIndirectCriterionRequirementFromOrderLine(orderLine))) {
            basicAddCriterionRequirementIntoOrderLineGroup(orderLineGroup, newRequirement);
        }
    }

    protected abstract Set<DirectCriterionRequirement> getDirectCriterionRequirementFromOrderLine(S orderLine);

    protected abstract Set<IndirectCriterionRequirement> getIndirectCriterionRequirementFromOrderLine(S orderLine);

    protected abstract void basicAddCriterionRequirementIntoOrderLineGroup(
            R orderLineGroup,
            CriterionRequirement criterionRequirement);

    protected void copyRequirementToOrderLine(R orderLineGroup, S orderLine) {
        // copy the directCriterionRequirement
        for (DirectCriterionRequirement newRequirement : copyDirectRequirements(
                getDirectCriterionRequirementFromOrderLineGroup(orderLineGroup))) {
            addDirectCriterionRequirementToOrderLine(orderLine, newRequirement);
        }
        // copy the IndirectCriterionRequirement
        for (IndirectCriterionRequirement newRequirement : copyIndirectRequirements(
                getIndirectCriterionRequirementFromOrderLineGroup(orderLineGroup))) {
            addIndirectCriterionRequirementToOrderLine(orderLine, newRequirement);
            propagateIndirectCriterionRequirementToOrderLineChildren(orderLine,
                    newRequirement.getParent());
        }
    }

    protected abstract Set<DirectCriterionRequirement>
        getDirectCriterionRequirementFromOrderLineGroup(R orderLineGroup);

    protected abstract void addIndirectCriterionRequirementToOrderLine(S orderLine, IndirectCriterionRequirement indirect);

    protected abstract Set<IndirectCriterionRequirement> getIndirectCriterionRequirementFromOrderLineGroup(R orderLineGroup);

    private Set<DirectCriterionRequirement> copyDirectRequirements(
            Set<DirectCriterionRequirement> collection) {
        Set<DirectCriterionRequirement> result = new HashSet<DirectCriterionRequirement>();
        for (DirectCriterionRequirement requirement : collection) {
            DirectCriterionRequirement newRequirement = DirectCriterionRequirement
                    .create(requirement.getCriterion());
            result.add(newRequirement);
        }
        return result;
    }

    private Set<IndirectCriterionRequirement> copyIndirectRequirements(
            Set<IndirectCriterionRequirement> collection) {
        Set<IndirectCriterionRequirement> result = new HashSet<IndirectCriterionRequirement>();
        for (IndirectCriterionRequirement requirement : collection) {
            DirectCriterionRequirement parent = requirement.getParent();
            IndirectCriterionRequirement newRequirement = IndirectCriterionRequirement
                    .create(parent, requirement.getCriterion());
            newRequirement.setValid(requirement.isValid());
            result.add(newRequirement);
        }
        return result;
    }

    Set<CriterionRequirement> getRequirementWithSameResourType(
            Set<CriterionRequirement> requirements, ResourceEnum resourceType) {
        Set<CriterionRequirement> result = new HashSet<CriterionRequirement>();
        for (CriterionRequirement requirement : requirements) {
            ResourceEnum resourceTypeParent = requirement.getCriterion()
                    .getType().getResource();
            if (resourceTypeParent.equals(resourceType)) {
                result.add(requirement);
            }
        }
        return result;
    }

    /**
     * Filters {@link DirectCriterionRequirement} from criterionRequirements
     *
     * @param criterionRequirements
     * @return
     */
    public Set<DirectCriterionRequirement> getDirectCriterionRequirement(
            Set<CriterionRequirement> criterionRequirements) {

        Set<DirectCriterionRequirement> list = new HashSet<DirectCriterionRequirement>();

        for (CriterionRequirement criterionRequirement : criterionRequirements) {
            if (criterionRequirement instanceof DirectCriterionRequirement) {
                list.add((DirectCriterionRequirement) criterionRequirement);
            }
        }
        return list;
    }

    public Set<IndirectCriterionRequirement> getIndirectCriterionRequirement(
            Set<CriterionRequirement> criterionRequirements) {

        Set<IndirectCriterionRequirement> list = new HashSet<IndirectCriterionRequirement>();

        for (CriterionRequirement criterionRequirement : criterionRequirements) {
            if (criterionRequirement instanceof IndirectCriterionRequirement) {
                list.add((IndirectCriterionRequirement) criterionRequirement);
            }
        }
        return list;
    }

    public void addCriterionRequirement(T orderElement,
            CriterionRequirement criterionRequirement) {
        if (criterionRequirement instanceof DirectCriterionRequirement) {
            addDirectCriterionRequirement(orderElement, (DirectCriterionRequirement) criterionRequirement);
        } else { // criterionRequirement instanceof IndirectCriterionRequirement
            addIndirectCriterionRequirement(orderElement, (IndirectCriterionRequirement) criterionRequirement);
        }
    }

    public void addDirectCriterionRequirement(T orderElement,
            CriterionRequirement newRequirement) {
        if (canAddCriterionRequirement(orderElement,
                newRequirement)) {
            basicAddCriterionRequirement(orderElement, newRequirement);
            propagateDirectCriterionRequirementAddition(orderElement,
                            newRequirement);
        } else {
            throw new IllegalStateException(
                    _("The criterion already exists into another task"));
        }
    }

    public void addIndirectCriterionRequirement(T orderElement,
            IndirectCriterionRequirement criterionRequirement) {
        basicAddCriterionRequirement(orderElement, criterionRequirement);
    }

    protected void addDirectCriterionRequirementToOrderLine(S orderLine, DirectCriterionRequirement direct) {
        addDirectCriterionRequirement(toOrderElement(orderLine), direct);
    }

    public void updateMyCriterionRequirements(T orderElement) {
        final T parent = getParent(orderElement);

        if (parent != null) {
            Set<CriterionRequirement> requirementsParent = getCriterionRequirements(parent);
            Set<IndirectCriterionRequirement> currentIndirects = getCurrentIndirectRequirements(
                    getIndirectCriterionRequirement(orderElement),
                    requirementsParent);
            transformDirectToIndirectIfNeeded(orderElement, currentIndirects);
            removeOldIndirects(orderElement, currentIndirects);
            addNewsIndirects(orderElement, currentIndirects);
        }
    }

    protected abstract T getParent(T orderElement);

    /**
     * Propagates {@link IndirectCriterionRequirement} for an
     * {@link OrderElement} or {@link OrderElementTemplate} preserving its valid
     * attribute
     *
     */
    public void propagateIndirectCriterionRequirementsForOrderLineGroupKeepingValid(
            R orderLineGroup,
            DirectCriterionRequirement parent) {

        copyIndirectCriterionRequirementsFromOriginalToOrderLineGroupChildren(
                orderLineGroup, parent);
        copyIndirectCriterionRequirementsFromOriginalToHoursGroup(
                orderLineGroup, parent);
    }

    public abstract void copyIndirectCriterionRequirementsFromOriginalToOrderLineGroupChildren(
            R orderLineGroup,
            DirectCriterionRequirement parent);

    public void copyIndirectCriterionRequirementsFromOriginalToHoursGroup(
            R orderLineGroup,
            DirectCriterionRequirement parent) {

        final List<T> orderElements = getOrderLineGroupChildren(orderLineGroup);
        final Criterion criterion = parent.getCriterion();
        final Set<IndirectCriterionRequirement> originalIndirectCriterionRequirements = parent
                .getOrigin().getChildren();
        final Map<HoursGroup, Map<Criterion, Boolean>> mapHoursGroup =
            createHoursGroupCriterionMap(originalIndirectCriterionRequirements);

        for (T each: orderElements) {

            IndirectCriterionRequirement indirect = IndirectCriterionRequirement
                    .create(parent, criterion);

            if (isOrderLine(each)) {
                for (HoursGroup hoursGroup: myHoursGroups(toOrderLine(each))) {
                    Map<Criterion, Boolean> criterionMap = mapHoursGroup.get(hoursGroup.getOrigin());
                    if (criterionMap != null) {
                        final Boolean valid = criterionMap.get(indirect.getCriterion());
                        indirect.setValid(valid);
                    }
                    hoursGroup.addCriterionRequirement(indirect);
                }
            }

            if (isOrderLineGroup(each)) {
                copyIndirectCriterionRequirementsFromOriginalToHoursGroup(
                        toOrderLineGroup(each), parent);
            }

        }
    }

    protected abstract boolean isOrderLineGroup(T orderElement);

    protected abstract Collection<HoursGroup> myHoursGroups(S orderline);

    /**
     * Creates a mapping between {@link HoursGroup} and a tuple (criterion,
     * boolean) from a list of {@link IndirectCriterionRequirement}
     *
     * The valid value of an {@link IndirectCriterionRequirement} can be later
     * retrieve knowing its {@link HoursGroup} and its {@link Criterion}
     *
     * This data structure is used to keep the original valid value from
     * {@link IndirectCriterionRequirement} when copying an {@link Order} to a
     * {@link Template} or vice-versa
     *
     * @param indirects
     * @return
     */
    private Map<HoursGroup, Map<Criterion, Boolean>> createHoursGroupCriterionMap(
            Set<IndirectCriterionRequirement> indirects) {

        Map<HoursGroup, Map<Criterion, Boolean>> result =
            new HashMap<HoursGroup, Map<Criterion, Boolean>>();

        for (IndirectCriterionRequirement each: indirects) {
            final HoursGroup hoursGroup = each.getHoursGroup();
            if (hoursGroup != null) {
                Map<Criterion, Boolean> value = result.get(hoursGroup);
                if (value == null) {
                    value = new HashMap<Criterion, Boolean>();
                }
                value.put(each.getCriterion(), each.isValid());
                result.put(hoursGroup, value);
            }
        }
        return result;
    }

}
TOP

Related Classes of org.libreplan.business.orders.entities.CriterionRequirementHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.