org.jdbcluster.domain.DomainCheckerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.jdbcluster.domain.DomainCheckerImpl.java

Source

/*
 * Copyright 2002-2005 the original author or authors.
 * 
 * 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.jdbcluster.domain;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.log4j.Logger;
import org.jdbcluster.JDBClusterUtil;
import org.jdbcluster.exception.ConfigurationException;
import org.jdbcluster.exception.DomainException;
import org.jdbcluster.metapersistence.annotation.AddDomainDependancy;
import org.jdbcluster.metapersistence.annotation.Domain;
import org.jdbcluster.metapersistence.annotation.DomainDependancy;
import org.jdbcluster.metapersistence.annotation.PrivilegesDomain;
import org.jdbcluster.metapersistence.cluster.ICluster;
import org.jdbcluster.metapersistence.security.user.IUser;
import org.jdbcluster.privilege.PrivilegeChecker;
import org.jdbcluster.privilege.PrivilegeCheckerImpl;
import org.springframework.util.Assert;

/**
 * checks slave domains for valid String values (I am really unlucky with this
 * code) 1. valid or invalid tags with value attribute 2. valid tags with all
 * attribute 3. invalid tags with all attribute
 * 
 * @author Christopher Schmidt
 * @author FaKod
 */
public class DomainCheckerImpl extends DomainBase implements DomainChecker {

    /**
     * Logger instance
     */
    private Logger logger = Logger.getLogger(this.getClass());

    /**
     * private ctor
     */
    private DomainCheckerImpl() {
    }

    /**
     * public instance getter
     * 
     * @return DomainChecker
     */
    public static DomainChecker getInstance() {
        return getImplInstance();
    }

    /**
     * package instance getter
     * 
     * @return DomainCheckerImpl
     */
    static DomainCheckerImpl getImplInstance() {
        return new DomainCheckerImpl();
    }

    /**
     * returns the corresponding domain id
     * 
     * @param cluster Cluster object to use
     * @param propPath path to the master or slave property
     * @return String domain id
     */
    public String getDomainId(ICluster cluster, String propPath) {

        Assert.notNull(cluster, "Cluster may not be null");
        Assert.hasLength(propPath, "propPath may not be null");

        if (logger.isDebugEnabled())
            logger.debug("getDomainId for cluster [" + cluster.getClass().getName() + "] and Property Path ["
                    + propPath + "]");

        String domId;
        Field fSlave = JDBClusterUtil.getField(propPath, cluster);

        DomainDependancy dd = fSlave.getAnnotation(DomainDependancy.class);
        if (dd == null) {
            Domain d = fSlave.getAnnotation(Domain.class);
            if (d == null)
                throw new ConfigurationException(
                        "no annotation @DomainDependancy or @Domain found on: " + propPath);
            domId = d.domainId();
        } else
            domId = dd.domainId();

        if (logger.isDebugEnabled())
            logger.debug("returning domain id [" + domId + "]");

        return domId;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.jdbcluster.domain.DomainChecker#check(org.jdbcluster.metapersistence.cluster.Cluster,
     *      java.lang.String)
     */
    public boolean check(ICluster cluster, String propSlavePath) {

        Assert.notNull(cluster, "Cluster may not be null");
        Assert.hasLength(propSlavePath, "propSlavePath may not be null");

        Field fSlave = JDBClusterUtil.getField(propSlavePath, cluster);
        String slaveValue = (String) JDBClusterUtil.invokeGetPropertyMethod(propSlavePath, cluster);
        DomainDependancy ddSlave = fSlave.getAnnotation(DomainDependancy.class);

        if (logger.isDebugEnabled())
            logger.debug("check for cluster [" + cluster.getClass().getName() + "] and Property Slave Path ["
                    + propSlavePath + "] and Slave Value [" + slaveValue + "] and Domain Dependancy Domain Id ["
                    + ddSlave.domainId() + "]");

        return check(cluster, fSlave, slaveValue, ddSlave);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.jdbcluster.domain.DomainChecker#check(org.jdbcluster.metapersistence.cluster.Cluster,
     *      java.lang.String, java.lang.Object)
     */
    public boolean check(ICluster cluster, String propSlavePath, Object propValue) {

        Assert.notNull(cluster, "Cluster may not be null");
        Assert.hasLength(propSlavePath, "propSlavePath may not be null");

        if (propValue instanceof String) {
            String slaveValue = (String) propValue;
            Field fSlave = JDBClusterUtil.getField(propSlavePath, cluster);
            DomainDependancy ddSlave = fSlave.getAnnotation(DomainDependancy.class);

            if (logger.isDebugEnabled())
                logger.debug("check for cluster [" + cluster.getClass().getName() + "] and Property Slave Path ["
                        + propSlavePath + "] and Slave Value [" + slaveValue + "] and Domain Dependancy Domain Id ["
                        + ddSlave.domainId() + "]");

            return check(cluster, fSlave, slaveValue, ddSlave);
        }
        throw new DomainException("while checking property [" + propSlavePath + "] and value [" + propValue + "]"
                + " at Cluster [" + cluster + "]." + " Property is not of type " + String.class.getName());
    }

    /**
     * for package wide use
     * 
     * @param cluster cluster instance
     * @param fSlave field of the slave domain
     * @param slaveValue the value to check
     * @param ddSlave the annotation
     * @return true if value is allowed
     */
    boolean check(ICluster cluster, Field fSlave, String slaveValue, DomainDependancy ddSlave) {

        String slaveDomainId = getDomainIdFromField(fSlave, true);
        String propMasterPath = ddSlave.dependsFromProperty();

        Field fMaster = JDBClusterUtil.getField(propMasterPath, cluster);
        String masterDomainId = getDomainIdFromField(fMaster, false);

        String masterValue = (String) JDBClusterUtil.invokeGetPropertyMethod(ddSlave.dependsFromProperty(),
                cluster);

        // check if there are additional depenancies
        if (!fSlave.isAnnotationPresent(AddDomainDependancy.class))
            return check(masterDomainId, masterValue, slaveDomainId, slaveValue);

        AddDomainDependancy aDD = fSlave.getAnnotation(AddDomainDependancy.class);
        String[] addDomIdArr = new String[aDD.addDepFromProp().length];
        String[] addDomValArr = new String[aDD.addDepFromProp().length];
        for (int i = 0; i < aDD.addDepFromProp().length; i++) {

            Field faddMaster = JDBClusterUtil.getField(aDD.addDepFromProp()[i], cluster);
            String addMasterDomainId = getDomainIdFromField(faddMaster, false);

            addDomIdArr[i] = addMasterDomainId;
            addDomValArr[i] = (String) JDBClusterUtil.invokeGetPropertyMethod(aDD.addDepFromProp()[i], cluster);
        }
        return check(masterDomainId, masterValue, slaveDomainId, slaveValue, addDomIdArr, addDomValArr);
    }

    /**
     * Main method for domain checking
     * 
     * @param masterDomainId configured master domain id (fe. "ColorTypeDomain")
     * @param masterValue the master entry (fe. "Color", "BlackWhite")
     * @param slaveDomainId configured slave domain id (fe. "ColorDomain")
     * @param slaveValue the slave entry (fe. "RED", "BLACK")
     * @return true if the slave value is allowed. Otherwise false (quel surprise)
     */
    boolean check(String masterDomainId, String masterValue, String slaveDomainId, String slaveValue) {
        if (!checkAgainstPossibleDomainEntries(slaveDomainId, slaveValue))
            return false;

        EntrySet es = getDomainConfig().getEntrySet(masterDomainId);
        if (es == null)
            throw new ConfigurationException(
                    "while checking domainId [" + slaveDomainId + "] and value [" + slaveValue + "]"
                            + " master domain [" + masterDomainId + "] annotated [@Domain] but not configured");

        HashMap<String, ValidEntryList> slaveEntries = es.get(masterValue == null ? "" : masterValue);
        if (slaveEntries == null) {
            if (es.get("*") == null)
                throw new DomainException("while checking domainId [" + slaveDomainId + "] and value [" + slaveValue
                        + "]" + " master domain [" + masterDomainId + "]: value [" + masterValue
                        + "] is not configured");
            else
                return true; // wildcard match
        }
        return validate(slaveEntries.get(slaveDomainId), slaveValue);
    }

    /**
     * Main method for domain checking with additional master
     * 
     * @param masterDomainId configured master domain id (fe. "ColorTypeDomain")
     * @param masterValue the master entry (fe. "Color", "BlackWhite")
     * @param slaveDomainId configured slave domain id (fe. "ColorDomain")
     * @param slaveValue the slave entry (fe. "RED", "BLACK")
     * @param addMasterDomainId array of additional master ids
     * @param addMasterValue array of additional master values
     * @return true if the slave value is allowed. Otherwise false (quel surprise)
     */
    boolean check(String masterDomainId, String masterValue, String slaveDomainId, String slaveValue,
            String[] addMasterDomainId, String[] addMasterValue) {
        if (!checkAgainstPossibleDomainEntries(slaveDomainId, slaveValue))
            return false;

        EntrySet es = getDomainConfig().getEntrySet(masterDomainId);
        if (es == null)
            throw new ConfigurationException(
                    "while checking domainId [" + slaveDomainId + "] and value [" + slaveValue + "]"
                            + "master domain [" + masterDomainId + "] annotated [@Domain] but not configured");

        if (masterValue == null)
            masterValue = "";

        HashMap<String, ValidEntryList> slaveEntries = es.get(masterValue);
        if (slaveEntries == null) {
            if (es.get("*") == null)
                throw new DomainException("while checking domainId [" + slaveDomainId + "] and value [" + slaveValue
                        + "]" + " master domain [" + masterDomainId + "]: Value [" + masterValue
                        + "] is not configured. \nUse <entry value=\"*\" slavedomainid=\"" + slaveDomainId + "\"/>"
                        + "\nIn definition of domain id " + masterDomainId);
            else
                return true; // wildcard match
        }
        boolean hadInvalidEntries = false;
        boolean hadValidEntries = false;
        ValidEntryList vel = slaveEntries.get(slaveDomainId);
        ArrayList<ValidEntryList> v = vel.getValidFromDomainEntry(addMasterDomainId, addMasterValue);

        for (int i = v.size() - 1; i >= 0; i--) {
            ValidEntryList ved = v.get(i);
            Valid validDomEntry = ved.getValidFromDomainEntry(slaveValue);
            if (validDomEntry != null) {
                return validDomEntry.valid;
            }
        }

        for (int i = v.size() - 1; i >= 0; i--) {
            ValidEntryList ved = v.get(i);
            if (!ved.isEmpty())
                return validate(ved, slaveValue);

            if (ved.isContainsInValidElements())
                hadInvalidEntries = true;
            if (ved.isContainsValidElements())
                hadValidEntries = true;
        }
        if (hadInvalidEntries && !hadValidEntries)
            return true;
        if (!hadInvalidEntries && !hadValidEntries)
            return true;
        if (!hadInvalidEntries && hadValidEntries)
            return false;
        if (hadInvalidEntries && hadValidEntries)
            return false;
        return false;
    }

    /**
     * IMPLEMENTATION calculates set of valid domain values (master or slave)
     * 
     * @param cluster Cluster object to use
     * @param propPath path to the master or slave property
     * @return ValidDomainEntries<String> with the valid domain values
     */
    public ValidDomainEntries<String> getValidDomainEntries(ICluster cluster, String propPath) {

        Assert.notNull(cluster, "Cluster may not be null");
        Assert.hasLength(propPath, "propPath may not be null");

        if (logger.isDebugEnabled())
            logger.debug("getValidDomainEntries for Cluster [" + cluster.getClass().getName() + "]"
                    + " and property path [" + propPath + "]");

        String masterDomainId;
        String masterValue;
        String slaveDomainId;

        Field fMaster;
        Field fSlave;

        fSlave = JDBClusterUtil.getField(propPath, cluster);

        DomainDependancy dd = fSlave.getAnnotation(DomainDependancy.class);
        if (dd == null) {
            Domain d = fSlave.getAnnotation(Domain.class);
            if (d == null)
                throw new ConfigurationException(
                        "no annotation @DomainDependancy or @Domain found on: " + propPath);

            if (logger.isDebugEnabled())
                logger.debug("getValidDomainEntries doing rightsIntersection for domain id[" + d.domainId() + "]"
                        + " and Field [" + fSlave.getName() + "]");

            return rightsIntersection(cluster.getUser(), getPossibleDomainEntries(d.domainId()), d.domainId(),
                    fSlave);
        }
        slaveDomainId = dd.domainId();

        String propMasterPath = dd.dependsFromProperty();
        fMaster = JDBClusterUtil.getField(propMasterPath, cluster);
        masterDomainId = getDomainIdFromField(fMaster, false);

        masterValue = (String) JDBClusterUtil.invokeGetPropertyMethod(dd.dependsFromProperty(), cluster);
        if (!fSlave.isAnnotationPresent(AddDomainDependancy.class)) {

            if (logger.isDebugEnabled())
                logger.debug("getValidDomainEntries doing rightsIntersection for master domain id[" + masterDomainId
                        + "]" + " and masterValue [" + masterValue + "]" + " and slaveDomainId [" + slaveDomainId
                        + "] and Field [" + fSlave.getName() + "]");

            return rightsIntersection(cluster.getUser(),
                    getValidDomainEntries(masterDomainId, masterValue, slaveDomainId), slaveDomainId, fSlave);
        }

        AddDomainDependancy aDD = fSlave.getAnnotation(AddDomainDependancy.class);
        String[] addDomIdArr = new String[aDD.addDepFromProp().length];
        String[] addDomValArr = new String[aDD.addDepFromProp().length];
        for (int i = 0; i < aDD.addDepFromProp().length; i++) {

            Field faddMaster = JDBClusterUtil.getField(aDD.addDepFromProp()[i], cluster);
            String addMasterDomainId = getDomainIdFromField(faddMaster, false);

            addDomIdArr[i] = addMasterDomainId;
            addDomValArr[i] = (String) JDBClusterUtil.invokeGetPropertyMethod(aDD.addDepFromProp()[i], cluster);
        }

        if (logger.isDebugEnabled())
            logger.debug("getValidDomainEntries (additional master) doing rightsIntersection for master domain id["
                    + masterDomainId + "]" + " and masterValue [" + masterValue + "]" + " and slaveDomainId ["
                    + slaveDomainId + "] and Field [" + fSlave.getName() + "]");

        return rightsIntersection(cluster.getUser(),
                getValidDomainEntries(masterDomainId, masterValue, slaveDomainId, addDomIdArr, addDomValArr),
                slaveDomainId, fSlave);
    }

    /**
     * calculates set of valid domain values (master or slave)
     * 
     * @param masterDomainId master domain id
     * @param masterValue master value
     * @param slaveDomainId slave domain id
     * @param addMasterDomainId array of additional master domain ids
     * @param addMasterValue array of additional master domain values
     * @return ValidDomainEntries<String> of all valid domain entries
     */
    ValidDomainEntries<String> getValidDomainEntries(String masterDomainId, String masterValue,
            String slaveDomainId, String[] addMasterDomainId, String[] addMasterValue) {
        ValidDomainEntries<String> wholeList = getValidDomainEntries(masterDomainId, masterValue, slaveDomainId);
        ValidDomainEntries<String> possibleValueList = getPossibleDomainEntries(slaveDomainId);

        EntrySet es = getDomainConfig().getEntrySet(masterDomainId);
        if (es == null)
            throw new ConfigurationException("slave domain [" + slaveDomainId + "].\n master domain ["
                    + masterDomainId + "] annotated [@Domain] but not configured");

        if (masterValue == null)
            masterValue = "";

        HashMap<String, ValidEntryList> slaveEntries = es.get(masterValue);
        if (slaveEntries == null) {
            EntrySet slaveEs = getDomainConfig().getEntrySet(slaveDomainId);
            if (slaveEs.get("*") == null)
                throw new DomainException("slave domain [" + slaveDomainId + "].\n master domain [" + masterDomainId
                        + "]: value [" + masterValue + "] is not configured");
            else
                return wholeList; // wildcard match
        }

        ValidDomainEntries<String> resultList = new ValidDomainEntries<String>();
        ValidEntryList valid = slaveEntries.get(slaveDomainId);

        for (String domEntry : wholeList) {
            if (validate(valid, domEntry)) {
                resultList.add(domEntry);
            }
        }
        if (validate(valid, null)) {
            resultList.setNullAllowed(true);
        }

        ArrayList<ValidEntryList> al = valid.getValidFromDomainEntry(addMasterDomainId, addMasterValue);

        for (int i = 0; i < al.size(); i++) {
            ValidEntryList ved = al.get(i);

            HashMap<String, Valid> mapToValids = ved.getMapValuesToValid();
            for (String s : mapToValids.keySet()) {
                Valid v = mapToValids.get(s);
                if (v.valid) {
                    if (!resultList.contains(s))
                        if (possibleValueList.contains(s))
                            resultList.add(s);
                } else {
                    resultList.remove(s);
                }
            }
        }

        for (int i = 0; i < al.size(); i++) {
            ValidEntryList ved = al.get(i);

            for (Valid v : ved) {
                if (v.valid) {
                    if (v.value == null)
                        resultList.setNullAllowed(v.nullValue);
                    else if (!resultList.contains(v.value))
                        resultList.add(v.value);
                } else {
                    if (v.value == null)
                        resultList.setNullAllowed(!v.nullValue);
                    else
                        resultList.remove(v.value);
                }
            }
        }
        return resultList;
    }

    /**
     * returns all valid values for domain slaveDomainId
     * 
     * @param masterDomainId the master entry (fe. "Color", "BlackWhite")
     * @param masterValue the master entry (fe. "Color", "BlackWhite")
     * @param slaveDomainId configured slave domain id (fe. "ColorDomain")
     * @return ordered list of valid domain entries
     */
    ValidDomainEntries<String> getValidDomainEntries(String masterDomainId, String masterValue,
            String slaveDomainId) {
        ValidDomainEntries<String> wholeList = getPossibleDomainEntries(slaveDomainId);

        EntrySet es = getDomainConfig().getEntrySet(masterDomainId);
        if (es == null)
            throw new ConfigurationException("slave domain [" + slaveDomainId + "].\n master domain ["
                    + masterDomainId + "] annotated [@Domain] but not configured");

        if (masterValue == null)
            masterValue = "";

        HashMap<String, ValidEntryList> slaveEntries = es.get(masterValue);
        if (slaveEntries == null) {
            EntrySet slaveEs = getDomainConfig().getEntrySet(slaveDomainId);
            if (slaveEs.get("*") == null)
                throw new DomainException("slave domain [" + slaveDomainId + "].\n master domain [" + masterDomainId
                        + "]: value [" + masterValue + "] is not configured");
            else
                return wholeList; // wildcard match
        }

        ValidDomainEntries<String> resultList = new ValidDomainEntries<String>();
        ValidEntryList valid = slaveEntries.get(slaveDomainId);

        if (valid == null) {
            throw new ConfigurationException("slave domain [" + slaveDomainId + "].\n master domain ["
                    + masterDomainId + "] annotated [@Domain] but slaveDomain not configured");
        }

        for (String domEntry : wholeList) {
            if (validate(valid, domEntry)) {
                resultList.add(domEntry);
            }
        }
        if (validate(valid, null)) {
            resultList.setNullAllowed(true);
        }
        return resultList;
    }

    /**
     * returns whole list for the specified domain
     * 
     * @param domainId domain id
     */
    public ValidDomainEntries<String> getPossibleDomainEntries(String domainId) {
        return new ValidDomainEntries<String>(getDomainListInstance(domainId).getDomainEntryList(domainId));
    }

    /**
     * checks the given slave value against all possible values
     * 
     * @param slaveDomainId slave domain id
     * @param slaveValue slave domain value
     * @return true if value is allowed
     */
    boolean checkAgainstPossibleDomainEntries(String slaveDomainId, String slaveValue) {
        ValidDomainEntries<String> vde = getPossibleDomainEntries(slaveDomainId);
        if (slaveValue == null)
            return vde.isNullAllowed();
        if (vde.contains(slaveValue))
            return true;
        return false;
    }

    /**
     * inersect all domain values with user rights if the richts are not
     * sufficient, the values will be removed
     * 
     * @param vde the list of domain values
     * @param domainId the domain id
     * @return
     */
    ValidDomainEntries<String> rightsIntersection(IUser user, ValidDomainEntries<String> vde, String domainId,
            Field f) {
        if (f.isAnnotationPresent(PrivilegesDomain.class)) {
            PrivilegeChecker pc = PrivilegeCheckerImpl.getInstance();
            ArrayList<String> al = new ArrayList<String>();
            for (String value : vde) {
                if (!pc.userPrivilegeIntersectDomain(user, domainId, value))
                    al.add(value);
            }
            vde.removeAll(al);
        }
        return vde;
    }

}