/*
 * Copyright 2001-2008 The Apache Software Foundation.
 * 
 * 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.apache.juddi.validation;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.xml.ws.Holder;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.juddi.api_v3.AccessPointType;
import org.apache.juddi.api_v3.DeleteClerk;
import org.apache.juddi.api_v3.DeleteNode;
import org.apache.juddi.api_v3.DeletePublisher;
import org.apache.juddi.api_v3.SavePublisher;
import org.apache.juddi.config.AppConfig;
import org.apache.juddi.config.Constants;
import org.apache.juddi.config.Install;
import org.apache.juddi.config.PersistenceManager;
import org.apache.juddi.config.Property;
import org.apache.juddi.keygen.KeyGenerator;
import org.apache.juddi.keygen.KeyGeneratorFactory;
import org.apache.juddi.mapping.MappingModelToApi;
import org.apache.juddi.model.Publisher;
import org.apache.juddi.model.Tmodel;
import org.apache.juddi.model.UddiEntity;
import org.apache.juddi.model.UddiEntityPublisher;
import org.apache.juddi.query.FindBusinessByPublisherQuery;
import org.apache.juddi.query.FindTModelByPublisherQuery;
import org.apache.juddi.v3.client.UDDIConstants;
import org.apache.juddi.v3.client.UDDIConstantsV2;
import org.apache.juddi.v3.client.config.TokenResolver;
import org.apache.juddi.v3.client.cryptor.CryptorFactory;
import org.apache.juddi.v3.client.cryptor.DigSigUtil;
import org.apache.juddi.v3.error.AssertionNotFoundException;
import org.apache.juddi.v3.error.ErrorMessage;
import org.apache.juddi.v3.error.FatalErrorException;
import org.apache.juddi.v3.error.InvalidKeyPassedException;
import org.apache.juddi.v3.error.InvalidProjectionException;
import org.apache.juddi.v3.error.KeyUnavailableException;
import org.apache.juddi.v3.error.MaxEntitiesExceededException;
import org.apache.juddi.v3.error.UserMismatchException;
import org.apache.juddi.v3.error.ValueNotAllowedException;
import org.uddi.api_v3.AccessPoint;
import org.uddi.api_v3.AddPublisherAssertions;
import org.uddi.api_v3.AddressLine;
import org.uddi.api_v3.BindingTemplate;
import org.uddi.api_v3.BusinessEntity;
import org.uddi.api_v3.BusinessService;
import org.uddi.api_v3.DeleteBinding;
import org.uddi.api_v3.DeleteBusiness;
import org.uddi.api_v3.DeletePublisherAssertions;
import org.uddi.api_v3.DeleteService;
import org.uddi.api_v3.DeleteTModel;
import org.uddi.api_v3.Description;
import org.uddi.api_v3.DiscoveryURL;
import org.uddi.api_v3.Email;
import org.uddi.api_v3.HostingRedirector;
import org.uddi.api_v3.KeyedReference;
import org.uddi.api_v3.KeyedReferenceGroup;
import org.uddi.api_v3.Name;
import org.uddi.api_v3.OverviewDoc;
import org.uddi.api_v3.OverviewURL;
import org.uddi.api_v3.Phone;
import org.uddi.api_v3.SaveBinding;
import org.uddi.api_v3.SaveBusiness;
import org.uddi.api_v3.SaveService;
import org.uddi.api_v3.SaveTModel;
import org.uddi.api_v3.TModel;
import org.uddi.repl_v3.ReplicationConfiguration;
import org.uddi.sub_v3.Subscription;
import org.uddi.v3_service.DispositionReportFaultMessage;

/**
 * Provides validation of publish requests to Juddi
 *
 * @author <a href="mailto:jfaath@apache.org">Jeff Faath</a>
 * @author <a href="mailto:tcunning@apache.org">Tom Cunningham</a>
 * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a> Modified March
 * 2013 to validate string length and ref integrity
 *
 * Advisory, be careful calling AppConfig.getConfiguration() from within
 * validation functions, it may inadvertently cause infinite loops during the
 * Install phase
 * @see Install
 */
public class ValidatePublish extends ValidateUDDIApi {

        private static final Log log = LogFactory.getLog(ValidatePublish.class);

        /**
         * used from Install class
         *
         * @param publisher
         * @param nodeid
         * @see Install
         */
        public ValidatePublish(UddiEntityPublisher publisher, String nodeid) {
                super(publisher, nodeid);
        }

        public ValidatePublish(UddiEntityPublisher publisher) {
                super(publisher);
        }

        public void validateDeleteBusiness(EntityManager em, DeleteBusiness body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<String> entityKeyList = body.getBusinessKey();
                if (entityKeyList == null || entityKeyList.size() == 0) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.NoKeys"));
                }

                HashSet<String> dupCheck = new HashSet<String>();
                int i = 0;
                for (String entityKey : entityKeyList) {

                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        entityKeyList.set(i, entityKey);

                        boolean inserted = dupCheck.add(entityKey);
                        if (!inserted) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.DuplicateKey", entityKey));
                        }

                        Object obj = em.find(org.apache.juddi.model.BusinessEntity.class, entityKey);
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.BusinessNotFound", entityKey));
                        }

                        if (!publisher.isOwner((UddiEntity) obj) && !((Publisher) publisher).isAdmin()) {
                                throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", entityKey));
                        }

                        i++;
                }
        }

        public void validateDeleteService(EntityManager em, DeleteService body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<String> entityKeyList = body.getServiceKey();
                if (entityKeyList == null || entityKeyList.size() == 0) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.NoKeys"));
                }

                HashSet<String> dupCheck = new HashSet<String>();
                int i = 0;
                for (String entityKey : entityKeyList) {

                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        entityKeyList.set(i, entityKey);

                        boolean inserted = dupCheck.add(entityKey);
                        if (!inserted) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.DuplicateKey", entityKey));
                        }

                        Object obj = em.find(org.apache.juddi.model.BusinessService.class, entityKey);
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ServiceNotFound", entityKey));
                        }

                        //if you're are the owner, access granted
                        //if you are an admin && this item belongs to this node, access granted
                        //else denied
                        AccessCheck(obj, entityKey);
                        i++;
                }
        }

        public void validateDeleteBinding(EntityManager em, DeleteBinding body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<String> entityKeyList = body.getBindingKey();
                if (entityKeyList == null || entityKeyList.size() == 0) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.NoKeys"));
                }

                // Checking for duplicates and existence
                HashSet<String> dupCheck = new HashSet<String>();
                int i = 0;
                for (String entityKey : entityKeyList) {
                        validateKeyLength(entityKey);
                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        entityKeyList.set(i, entityKey);

                        boolean inserted = dupCheck.add(entityKey);
                        if (!inserted) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.DuplicateKey", entityKey));
                        }

                        Object obj = em.find(org.apache.juddi.model.BindingTemplate.class, entityKey);
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.BindingTemplateNotFound", entityKey));
                        }

                        AccessCheck(obj, entityKey);

                        i++;
                }
        }

        public void validateDeleteTModel(EntityManager em, DeleteTModel body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<String> entityKeyList = body.getTModelKey();
                if (entityKeyList == null || entityKeyList.size() == 0) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.NoKeys"));
                }

                HashSet<String> dupCheck = new HashSet<String>();
                int i = 0;
                for (String entityKey : entityKeyList) {
                        validateKeyLength(entityKey);
                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        entityKeyList.set(i, entityKey);

                        boolean inserted = dupCheck.add(entityKey);
                        if (!inserted) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.DuplicateKey", entityKey));
                        }

                        Object obj = em.find(org.apache.juddi.model.Tmodel.class, entityKey);
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.TModelNotFound", entityKey));
                        }

                        AccessCheck(obj, entityKey);

                        i++;
                }
        }

        private void AccessCheck(Object obj, String entityKey) throws UserMismatchException {
                boolean accessCheck = false; //assume access denied
                if (!((UddiEntity) obj).getNodeId().equals(nodeID)) {
                        //prevent changes to data owned by another node in a replicated environment
                        //even if you're the boss
                        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidNode", entityKey + " Owning Node: " + ((UddiEntity) obj).getNodeId()
                                + ", this node: " + nodeID));
                }

                if (publisher.isOwner((UddiEntity) obj) && nodeID.equals(((UddiEntity) obj).getNodeId())) {
                        accessCheck = true;

                }
                //if i'm an admin, let me edit stuff on this node, but only stuff that's owned by this node
                if (((Publisher) publisher).isAdmin()
                        && nodeID.equals(((UddiEntity) obj).getNodeId())) {
                        accessCheck = true;
                }

                if (!accessCheck) {
                        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", entityKey));
                }

        }

        public void validateDeletePublisherAssertions(EntityManager em, DeletePublisherAssertions body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.uddi.api_v3.PublisherAssertion> entityList = body.getPublisherAssertion();
                if (entityList == null || entityList.size() == 0) {
                        throw new AssertionNotFoundException(new ErrorMessage("errors.pubassertion.NoPubAssertions"));
                }

                for (org.uddi.api_v3.PublisherAssertion entity : entityList) {
                        validateKeyLength(entity.getFromKey());
                        validateKeyLength(entity.getToKey());
                        validatePublisherAssertion(em, entity);

                        org.apache.juddi.model.PublisherAssertionId pubAssertionId = new org.apache.juddi.model.PublisherAssertionId(entity.getFromKey(), entity.getToKey());
                        Object obj = em.find(org.apache.juddi.model.PublisherAssertion.class, pubAssertionId);
                        if (obj == null) {
                                throw new AssertionNotFoundException(new ErrorMessage("errors.pubassertion.AssertionNotFound", entity.getFromKey() + ", " + entity.getToKey()));
                        } else {
                                org.apache.juddi.model.PublisherAssertion pubAssertion = (org.apache.juddi.model.PublisherAssertion) obj;
                                org.uddi.api_v3.KeyedReference keyedRef = entity.getKeyedReference();
                                if (keyedRef == null) {
                                        throw new AssertionNotFoundException(new ErrorMessage("errors.pubassertion.AssertionNotFound", entity.getFromKey() + ", " + entity.getToKey()));
                                }

                                if (!pubAssertion.getTmodelKey().equalsIgnoreCase(keyedRef.getTModelKey())
                                        || !pubAssertion.getKeyName().equalsIgnoreCase(keyedRef.getKeyName())
                                        || !pubAssertion.getKeyValue().equalsIgnoreCase(keyedRef.getKeyValue())) {
                                        throw new AssertionNotFoundException(new ErrorMessage("errors.pubassertion.AssertionNotFound", entity.getFromKey() + ", " + entity.getToKey()));
                                }
                                //JUDDI-908
                                if (!publisher.isOwner(pubAssertion.getBusinessEntityByToKey())
                                        && !publisher.isOwner(pubAssertion.getBusinessEntityByFromKey())) {
                                        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.assertion"));
                                }

                        }

                }
        }

        public void validateSaveBusiness(EntityManager em, SaveBusiness body, Configuration config, UddiEntityPublisher publisher) throws DispositionReportFaultMessage {

                if (config == null) {
                        try {
                                config = AppConfig.getConfiguration();
                        } catch (ConfigurationException ce) {
                                log.error("Could not optain config. " + ce.getMessage(), ce);
                        }
                }
                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.uddi.api_v3.BusinessEntity> entityList = body.getBusinessEntity();
                if (entityList == null || entityList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.savebusiness.NoInput"));
                }

                for (org.uddi.api_v3.BusinessEntity entity : entityList) {
                        validateBusinessEntity(em, entity, config, publisher);

                }
                validateCheckedTModelsBE(entityList, config);
        }

        public void validateSaveBusinessMax(EntityManager em) throws DispositionReportFaultMessage {

                //Obtain the maxSettings for this publisher or get the defaults
                Publisher publisher = em.find(Publisher.class, getPublisher().getAuthorizedName());
                Integer maxBusinesses = publisher.getMaxBusinesses();
                try {
                        if (maxBusinesses == null) {
                                if (AppConfig.getConfiguration().containsKey(Property.JUDDI_MAX_BUSINESSES_PER_PUBLISHER)) {
                                        maxBusinesses = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_BUSINESSES_PER_PUBLISHER, -1);
                                } else {
                                        maxBusinesses = -1;
                                }
                        }
                } catch (ConfigurationException e) {
                        log.error(e.getMessage(), e);
                        maxBusinesses = -1; //in case the configuration is not available
                }
                //if we have the maxBusinesses set for this publisher then we need to make sure we did not exceed it.
                if (maxBusinesses > 0) {
                        //get the businesses owned by this publisher
                        List<?> businessKeysFound = FindBusinessByPublisherQuery.select(em, null, publisher, null);
                        if (businessKeysFound != null && businessKeysFound.size() > maxBusinesses) {
                                throw new MaxEntitiesExceededException(new ErrorMessage("errors.save.maxBusinessesExceeded"));
                        }
                }

        }

        public void validateSaveService(EntityManager em, SaveService body, Configuration config, UddiEntityPublisher publisher) throws DispositionReportFaultMessage {

                if (config == null) {
                        try {
                                config = AppConfig.getConfiguration();
                        } catch (ConfigurationException ce) {
                                log.error("Could not optain config. " + ce.getMessage(), ce);
                        }
                }
                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.uddi.api_v3.BusinessService> entityList = body.getBusinessService();
                if (entityList == null || entityList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.saveservice.NoInput"));
                }

                for (org.uddi.api_v3.BusinessService entity : entityList) {
                        // Entity specific data validation
                        validateBusinessService(em, entity, null, config, publisher);

                }
                validateCheckedTModelsBS(entityList, config);
        }

        public void validateSaveServiceMax(EntityManager em, String businessKey) throws DispositionReportFaultMessage {

                //Obtain the maxSettings for this publisher or get the defaults
                Publisher publisher = em.find(Publisher.class, getPublisher().getAuthorizedName());
                Integer maxServices = publisher.getMaxBusinesses();
                try {
                        if (maxServices == null) {
                                if (AppConfig.getConfiguration().containsKey(Property.JUDDI_MAX_SERVICES_PER_BUSINESS)) {
                                        maxServices = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_SERVICES_PER_BUSINESS, -1);
                                } else {
                                        maxServices = -1;
                                }
                        }
                } catch (ConfigurationException e) {
                        log.error(e.getMessage(), e);
                        maxServices = -1; //incase the configuration isn't available
                }
                //if we have the maxServices set for a business then we need to make sure we did not exceed it.
                if (maxServices > 0) {
                        //get the businesses owned by this publisher
                        org.apache.juddi.model.BusinessEntity modelBusinessEntity = em.find(org.apache.juddi.model.BusinessEntity.class, businessKey);
                        if (modelBusinessEntity.getBusinessServices() != null && modelBusinessEntity.getBusinessServices().size() > maxServices) {
                                throw new MaxEntitiesExceededException(new ErrorMessage("errors.save.maxServicesExceeded"));
                        }
                }
        }

        public void validateSaveBinding(EntityManager em, SaveBinding body, Configuration config, UddiEntityPublisher publisher) throws DispositionReportFaultMessage {

                if (config == null) {
                        try {
                                config = AppConfig.getConfiguration();
                        } catch (ConfigurationException ce) {
                                log.error("Could not optain config. " + ce.getMessage(), ce);
                        }
                }
                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.uddi.api_v3.BindingTemplate> entityList = body.getBindingTemplate();
                if (entityList == null || entityList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.savebinding.NoInput"));
                }

                for (org.uddi.api_v3.BindingTemplate entity : entityList) {
                        validateBindingTemplate(em, entity, null, config, publisher);

                }
                validateCheckedTModelsBT(entityList, config);
        }

        public void validateSaveBindingMax(EntityManager em, String serviceKey) throws DispositionReportFaultMessage {

                //Obtain the maxSettings for this publisher or get the defaults
                Publisher publisher = em.find(Publisher.class, getPublisher().getAuthorizedName());
                Integer maxBindings = publisher.getMaxBindingsPerService();
                try {
                        if (maxBindings == null) {
                                if (AppConfig.getConfiguration().containsKey(Property.JUDDI_MAX_BINDINGS_PER_SERVICE)) {
                                        maxBindings = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_BINDINGS_PER_SERVICE, -1);
                                } else {
                                        maxBindings = -1;
                                }
                        }
                } catch (ConfigurationException e) {
                        log.error(e.getMessage(), e);
                        maxBindings = -1; //incase the config isn't available
                }
                //if we have the maxBindings set for a service then we need to make sure we did not exceed it.
                if (maxBindings > 0) {
                        //get the bindings owned by this service
                        org.apache.juddi.model.BusinessService modelBusinessService = em.find(org.apache.juddi.model.BusinessService.class, serviceKey);
                        if (modelBusinessService.getBindingTemplates() != null && modelBusinessService.getBindingTemplates().size() > maxBindings) {
                                throw new MaxEntitiesExceededException(new ErrorMessage("errors.save.maxBindingsExceeded"));
                        }
                }
        }

        public void validateSaveTModel(EntityManager em, SaveTModel body, Configuration config, UddiEntityPublisher publisher) throws DispositionReportFaultMessage {

                if (config == null) {
                        try {
                                config = AppConfig.getConfiguration();
                        } catch (ConfigurationException ce) {
                                log.error("Could not optain config. " + ce.getMessage(), ce);
                        }
                }
                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.uddi.api_v3.TModel> entityList = body.getTModel();
                if (entityList == null || entityList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.savetmodel.NoInput"));
                }

                for (org.uddi.api_v3.TModel entity : entityList) {
                        validateTModel(em, entity, config, publisher);

                }
                validateCheckedTModelsTM(entityList, config);
        }

        public void validateSaveTModelMax(EntityManager em) throws DispositionReportFaultMessage {

                //Obtain the maxSettings for this publisher or get the defaults
                Publisher publisher = em.find(Publisher.class, getPublisher().getAuthorizedName());
                Integer maxTModels = publisher.getMaxTmodels();
                try {
                        if (maxTModels == null) {
                                if (AppConfig.getConfiguration().containsKey(Property.JUDDI_MAX_TMODELS_PER_PUBLISHER)) {
                                        maxTModels = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_TMODELS_PER_PUBLISHER, -1);
                                } else {
                                        maxTModels = -1;
                                }
                        }
                } catch (ConfigurationException e) {
                        log.error(e.getMessage(), e);
                        maxTModels = -1; //incase the config isn't available
                }
                //if we have the TModels set for a publisher then we need to make sure we did not exceed it.
                if (maxTModels > 0) {
                        //get the tmodels owned by this publisher
                        List<?> tmodelKeysFound = FindTModelByPublisherQuery.select(em, null, publisher, null);
                        if (tmodelKeysFound != null && tmodelKeysFound.size() > maxTModels) {
                                throw new MaxEntitiesExceededException(new ErrorMessage("errors.save.maxTModelsExceeded"));
                        }
                }
        }

        public void validateAddPublisherAssertions(EntityManager em, AddPublisherAssertions body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.uddi.api_v3.PublisherAssertion> entityList = body.getPublisherAssertion();
                if (entityList == null || entityList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.addpublisherassertions.NoInput"));
                }

                for (org.uddi.api_v3.PublisherAssertion entity : entityList) {
                        validatePublisherAssertion(em, entity);
                }
        }

        public void validateSetPublisherAssertions(EntityManager em, Holder<List<org.uddi.api_v3.PublisherAssertion>> body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // Assertion list can be null or empty - it signifies that publisher is deleting all their assertions
                List<org.uddi.api_v3.PublisherAssertion> entityList = body.value;
                if (entityList != null && entityList.size() > 0) {

                        for (org.uddi.api_v3.PublisherAssertion entity : entityList) {
                                validatePublisherAssertion(em, entity);
                        }
                }
        }

        void validateNotSigned(org.uddi.api_v3.BusinessEntity item) throws ValueNotAllowedException {
                if (item == null) {
                        return;
                }
                if (item.getBusinessKey() == null && !item.getSignature().isEmpty()) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "businessKey"));
                }
                if (item.getBusinessServices() != null && !item.getSignature().isEmpty()) {
                        for (int i = 0; i < item.getBusinessServices().getBusinessService().size(); i++) {
                                if (item.getBusinessServices().getBusinessService().get(i).getBusinessKey() == null
                                        || item.getBusinessServices().getBusinessService().get(i).getBusinessKey().length() == 0) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "business/Service(" + i + ")/businessKey"));
                                }
                                if (item.getBusinessServices().getBusinessService().get(i).getServiceKey() == null
                                        || item.getBusinessServices().getBusinessService().get(i).getServiceKey().length() == 0) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "business/Service(" + i + ")/serviceKey"));
                                }
                                if (item.getBusinessServices().getBusinessService().get(i).getBindingTemplates() != null) {
                                        for (int k = 0; k < item.getBusinessServices().getBusinessService().get(i).getBindingTemplates().getBindingTemplate().size(); k++) {
                                                if (item.getBusinessServices().getBusinessService().get(i).getBindingTemplates().getBindingTemplate().get(k).getBindingKey() == null
                                                        || item.getBusinessServices().getBusinessService().get(i).getBindingTemplates().getBindingTemplate().get(k).getBindingKey().length() == 0) {
                                                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "business/Service(" + i + ")/bindingTemplate)" + k + ")/bindingKey"));
                                                }
                                        }
                                }
                        }
                }
        }

        void validateNotSigned(org.uddi.api_v3.BindingTemplate item) throws ValueNotAllowedException {
                if (item == null) {
                        return;
                }
                if (item.getBindingKey() == null && !item.getSignature().isEmpty()) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "bindingKey"));
                }
                if (item.getServiceKey() == null && !item.getSignature().isEmpty()) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "serviceKey"));
                }
        }

        void validateNotSigned(org.uddi.api_v3.TModel item) throws ValueNotAllowedException {
                if (item == null) {
                        return;
                }
                if (item.getTModelKey() == null && !item.getSignature().isEmpty()) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "tModelKey"));
                }
        }

        void validateNotSigned(org.uddi.api_v3.BusinessService item) throws ValueNotAllowedException {
                if (item == null) {
                        return;
                }
                if (item.getBusinessKey() == null && !item.getSignature().isEmpty()) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "businessKey"));
                }
                if (item.getServiceKey() == null && !item.getSignature().isEmpty()) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "serviceKey"));
                }
                //if i'm signed and a key isn't defined in a bt
                if (item.getBindingTemplates() != null && !item.getSignature().isEmpty()) {
                        for (int i = 0; i < item.getBindingTemplates().getBindingTemplate().size(); i++) {
                                if (item.getBindingTemplates().getBindingTemplate().get(i).getBindingKey() == null
                                        || item.getBindingTemplates().getBindingTemplate().get(i).getBindingKey().length() == 0) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.entity.SignedButNoKey", "businessService/bindingTemplate(" + i + ")/bindingKey"));
                                }
                        }
                }
        }

        public void validateBusinessEntity(EntityManager em, org.uddi.api_v3.BusinessEntity businessEntity,
                Configuration config, UddiEntityPublisher publisher) throws DispositionReportFaultMessage {

                // A supplied businessEntity can't be null
                if (businessEntity == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.businessentity.NullInput"));
                }

                boolean entityExists = false;
                validateNotSigned(businessEntity);
                String entityKey = businessEntity.getBusinessKey();
                if (entityKey == null || entityKey.length() == 0) {
                        KeyGenerator keyGen = KeyGeneratorFactory.getKeyGenerator();
                        entityKey = keyGen.generate(publisher);
                        businessEntity.setBusinessKey(entityKey);
                } else {
                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        businessEntity.setBusinessKey(entityKey);
                        validateKeyLength(entityKey);
                        Object obj = em.find(org.apache.juddi.model.BusinessEntity.class, entityKey);
                        if (obj != null) {
                                entityExists = true;

                                // Make sure publisher owns this entity.
                                AccessCheck(obj, entityKey);

                        } else {
                                // Inside this block, we have a key proposed by the publisher on a new entity

                                // Validate key and then check to see that the proposed key is valid for this publisher
                                ValidateUDDIKey.validateUDDIv3Key(entityKey);
                                if (!publisher.isValidPublisherKey(em, entityKey)) {
                                        throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.BadPartition", entityKey));
                                }

                        }
                }

                if (!entityExists) {
                        // Check to make sure key isn't used by another entity.
                        if (!isUniqueKey(em, entityKey)) {
                                throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.KeyExists", entityKey));
                        }
                }

                // was TODO: validate "checked" categories or category groups (see section 5.2.3 of spec)? optional to support
                //covered by ref integrity checks
                validateNames(businessEntity.getName());
                validateDiscoveryUrls(businessEntity.getDiscoveryURLs());
                validateContacts(businessEntity.getContacts(), config);
                validateCategoryBag(businessEntity.getCategoryBag(), config, false);
                validateIdentifierBag(businessEntity.getIdentifierBag(), config, false);
                validateDescriptions(businessEntity.getDescription());
                validateBusinessServices(em, businessEntity.getBusinessServices(), businessEntity, config, publisher);
                validateSignaturesBusiness(businessEntity, config);

        }

        public void validateBusinessServices(EntityManager em, org.uddi.api_v3.BusinessServices businessServices,
                org.uddi.api_v3.BusinessEntity parent, Configuration config, UddiEntityPublisher publisher)
                throws DispositionReportFaultMessage {
                // Business services is optional
                if (businessServices == null) {
                        return;
                }
                List<org.uddi.api_v3.BusinessService> businessServiceList = businessServices.getBusinessService();
                if (businessServiceList == null || businessServiceList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.businessservices.NoInput"));
                }

                for (org.uddi.api_v3.BusinessService businessService : businessServiceList) {
                        validateBusinessService(em, businessService, parent, config, publisher);
                }

        }

        public void validateBusinessService(EntityManager em, org.uddi.api_v3.BusinessService businessService,
                org.uddi.api_v3.BusinessEntity parent, Configuration config, UddiEntityPublisher publisher)
                throws DispositionReportFaultMessage {

                // A supplied businessService can't be null
                if (businessService == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.businessservice.NullInput"));
                }

                validateNotSigned(businessService);
                // Retrieve the service's passed key
                String entityKey = businessService.getServiceKey();
                if (entityKey != null && entityKey.length() > 0) {
                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        validateKeyLength(entityKey);
                        businessService.setServiceKey(entityKey);
                }

                // The parent key is either supplied or provided by the higher call to the parent entity save.  If the passed-in parent's business key differs from 
                // the (non-null) business key retrieved from the service, then we have a possible service projection.
                String parentKey = businessService.getBusinessKey();
                if (parentKey != null && parentKey.length() > 0) {
                        // Per section 4.4: keys must be case-folded
                        parentKey = parentKey.toLowerCase();
                        businessService.setBusinessKey(parentKey);
                }

                boolean isProjection = false;
                if (parent != null) {
                        if (parentKey != null && parentKey.length() > 0) {
                                if (!parentKey.equalsIgnoreCase(parent.getBusinessKey())) {
                                        // Possible projected service - if we have differing parent businesses but a service key was not provided, this is an error as it is not possible 
                                        // for the business that doesn't "own" the service to generate the key for it.
                                        if (entityKey == null || entityKey.length() == 0) {
                                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ServiceKeyNotProvidedWithProjection", parentKey + ", " + parent.getBusinessKey()));
                                        }

                                        isProjection = true;
                                }
                        } else {
                                parentKey = parent.getBusinessKey();
                        }
                }

                // Projections don't require as rigorous testing as only the projected service's business key and service key are examined for validity.
                if (isProjection) {

                        Object obj = em.find(org.apache.juddi.model.BusinessService.class, entityKey);
                        // Can't project a service that doesn't exist!
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ProjectedServiceNotFound", parentKey + ", " + entityKey));
                        } else {
                                // If the supplied business key doesn't match the existing service's business key, the projection is invalid.
                                org.apache.juddi.model.BusinessService bs = (org.apache.juddi.model.BusinessService) obj;
                                if (!businessService.getBusinessKey().equalsIgnoreCase(bs.getBusinessEntity().getEntityKey())) {
                                        throw new InvalidProjectionException(new ErrorMessage("errors.invalidprojection.ParentMismatch", businessService.getBusinessKey() + ", " + bs.getBusinessEntity().getEntityKey()));
                                }
                        }
                        obj = null;
                } else {
                        boolean entityExists = false;
                        if (entityKey == null || entityKey.length() == 0) {
                                KeyGenerator keyGen = KeyGeneratorFactory.getKeyGenerator();
                                entityKey = keyGen.generate(publisher);
                                businessService.setServiceKey(entityKey);
                        } else {

                                Object obj = em.find(org.apache.juddi.model.BusinessService.class, entityKey);
                                if (obj != null) {
                                        entityExists = true;

                                        org.apache.juddi.model.BusinessService bs = (org.apache.juddi.model.BusinessService) obj;

                                        // If the object exists, and the parentKey was not found to this point, then a save on an existing service with a blank
                                        // business key has occurred.  It is set here and added to the entity being saved - a necessary step for the object to be
                                        // persisted properly. (This condition makes some validation tests below unnecessary as the parent is "verified" but it's OK to
                                        // still run them).
                                        if (parentKey == null || parentKey.length() == 0) {
                                                parentKey = bs.getBusinessEntity().getEntityKey();
                                                businessService.setBusinessKey(parentKey);
                                        }

                                        // Make sure publisher owns this entity.
                                        AccessCheck(obj, entityKey);

                                        // If existing service trying to be saved has a different parent key, then we have a problem
                                        if (!parentKey.equalsIgnoreCase(bs.getBusinessEntity().getEntityKey())) {
                                                // if both businesses are owned by this publisher then we allow it.
                                                // we already check the current business is owned, lets see if the old one is too
                                                if (!publisher.isOwner(bs.getBusinessEntity())) {
                                                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.businessservice.ParentMismatch", parentKey + ", " + bs.getBusinessEntity().getEntityKey()));
                                                } else {
                                                        if (log.isDebugEnabled()) {
                                                                log.debug("Services moved from business " + bs.getBusinessEntity() + " to " + businessService.getBusinessKey());
                                                        }
                                                }
                                        }

                                } else {
                                        // Inside this block, we have a key proposed by the publisher on a new entity

                                        // Validate key and then check to see that the proposed key is valid for this publisher
                                        ValidateUDDIKey.validateUDDIv3Key(entityKey);
                                        if (!publisher.isValidPublisherKey(em, entityKey)) {
                                                throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.BadPartition", entityKey));
                                        }

                                }

                        }

                        // Parent key must be passed if this is a new entity
                        if (!entityExists) {
                                if (parentKey == null || parentKey.length() == 0) {
                                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ParentBusinessNotFound", parentKey));
                                }
                        }

                        // If parent key IS passed, whether new entity or not, it must be valid.  Additionally, the current publisher must be the owner of the parent.  Note that
                        // if a parent ENTITY was passed in, then we don't need to check for any of this since this is part of a higher call.
                        if (parentKey != null) {
                                if (parent == null) {
                                        Object parentTemp = em.find(org.apache.juddi.model.BusinessEntity.class, parentKey);
                                        if (parentTemp == null) {
                                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ParentBusinessNotFound", parentKey));
                                        }

                                        // Make sure publisher owns this parent entity.
                                        AccessCheck(parentTemp, parentKey);
                                        // if (!publisher.isOwner((UddiEntity) parentTemp)) {
                                        //        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwnerParent", parentKey));
                                        //}
                                }
                        }

                        if (!entityExists) {
                                // Check to make sure key isn't used by another entity.
                                if (!isUniqueKey(em, entityKey)) {
                                        throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.KeyExists", entityKey));
                                }
                        }

                        // TODO: validate "checked" categories or category groups (see section 5.2.3 of spec)? optional to support
                        validateNames(businessService.getName());
                        validateCategoryBag(businessService.getCategoryBag(), config, false);
                        validateDescriptions(businessService.getDescription());
                        validateBindingTemplates(em, businessService.getBindingTemplates(), businessService, config, publisher);
                        validateSignaturesService(businessService, config);
                }

        }

        public void validateBindingTemplates(EntityManager em, org.uddi.api_v3.BindingTemplates bindingTemplates,
                org.uddi.api_v3.BusinessService parent, Configuration config, UddiEntityPublisher publisher)
                throws DispositionReportFaultMessage {
                // Binding templates is optional
                if (bindingTemplates == null) {
                        return;
                }

                List<org.uddi.api_v3.BindingTemplate> bindingTemplateList = bindingTemplates.getBindingTemplate();
                if (bindingTemplateList == null || bindingTemplateList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.bindingtemplates.NoInput"));
                }

                for (org.uddi.api_v3.BindingTemplate bindingTemplate : bindingTemplateList) {
                        validateBindingTemplate(em, bindingTemplate, parent, config, publisher);
                }

        }

        public void validateBindingTemplate(EntityManager em, org.uddi.api_v3.BindingTemplate bindingTemplate,
                org.uddi.api_v3.BusinessService parent, Configuration config, UddiEntityPublisher publisher)
                throws DispositionReportFaultMessage {

                // A supplied bindingTemplate can't be null
                if (bindingTemplate == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.bindingtemplate.NullInput"));
                }

                // Retrieve the binding's passed key
                String entityKey = bindingTemplate.getBindingKey();
                if (entityKey != null && entityKey.length() > 0) {
                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        bindingTemplate.setBindingKey(entityKey);
                        validateKeyLength(entityKey);
                }

                // The parent key is either supplied or provided by the higher call to the parent entity save.  If it is provided in both instances, if they differ, an 
                // error occurs.
                String parentKey = bindingTemplate.getServiceKey();
                if (parentKey != null && parentKey.length() > 0) {
                        // Per section 4.4: keys must be case-folded
                        parentKey = parentKey.toLowerCase();
                        bindingTemplate.setServiceKey(parentKey);
                }

                if (parent != null) {
                        if (parentKey != null && parentKey.length() > 0) {
                                if (!parentKey.equalsIgnoreCase(parent.getServiceKey())) {
                                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.bindingtemplate.ParentMismatch", parentKey + ", " + parent.getBusinessKey()));
                                }
                        } else {
                                parentKey = parent.getServiceKey();
                        }
                }

                boolean entityExists = false;
                if (entityKey == null || entityKey.length() == 0) {
                        validateNotSigned(bindingTemplate);
                        KeyGenerator keyGen = KeyGeneratorFactory.getKeyGenerator();
                        entityKey = keyGen.generate(publisher);
                        bindingTemplate.setBindingKey(entityKey);
                } else {

                        Object obj = em.find(org.apache.juddi.model.BindingTemplate.class, entityKey);
                        if (obj != null) {
                                entityExists = true;

                                org.apache.juddi.model.BindingTemplate bt = (org.apache.juddi.model.BindingTemplate) obj;

                                // If the object exists, and the parentKey was not found to this point, then a save on an existing binding with a blank
                                // service key has occurred.  It is set here and added to the entity being saved - a necessary step for the object to be
                                // persisted properly. (This condition makes some validation tests below unnecessary as the parent is "verified" but it's OK to
                                // still run them).
                                if (parentKey == null || parentKey.length() == 0) {
                                        parentKey = bt.getBusinessService().getEntityKey();
                                        bindingTemplate.setServiceKey(parentKey);
                                }

                                // If existing binding trying to be saved has a different parent key, then we have a problem
                                // TODO: moving bindings is allowed according to spec?
                                if (!parentKey.equalsIgnoreCase(bt.getBusinessService().getEntityKey())) {
                                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.bindingtemplate.ParentMismatch", parentKey + ", " + bt.getBusinessService().getEntityKey()));
                                }

                                // Make sure publisher owns this entity.
                                AccessCheck(obj, entityKey);
                                //if (!publisher.isOwner((UddiEntity) obj)&& !((Publisher) publisher).isAdmin()) {
//                                        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", entityKey));
                                //                              }

                        } else {
                                // Inside this block, we have a key proposed by the publisher on a new entity

                                // Validate key and then check to see that the proposed key is valid for this publisher
                                ValidateUDDIKey.validateUDDIv3Key(entityKey);
                                if (!publisher.isValidPublisherKey(em, entityKey)) {
                                        throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.BadPartition", entityKey));
                                }

                        }

                }

                // Parent key must be passed if this is a new entity
                if (!entityExists) {
                        if (parentKey == null || parentKey.length() == 0) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ParentServiceNotFound", parentKey));
                        }
                }

                // If parent key IS passed, whether new entity or not, it must be valid.  Additionally, the current publisher must be the owner of the parent.  Note that
                // if a parent ENTITY was passed in, then we don't need to check for any of this since this is part of a higher call.
                if (parentKey != null) {
                        if (parent == null) {
                                Object parentTemp = em.find(org.apache.juddi.model.BusinessService.class, parentKey);
                                if (parentTemp == null) {
                                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ParentBusinessNotFound", parentKey));
                                } else if (!(parentTemp instanceof org.apache.juddi.model.BusinessService)) {
                                        //JUDDI-848
                                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.ParentBusinessNotFound", parentKey));
                                }

                                // Make sure publisher owns this parent entity.
                                AccessCheck(parentTemp, parentKey);
//                                if (!publisher.isOwner((UddiEntity) parentTemp)) {
//                                        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwnerParent", parentKey));
//                                }

                        }
                }

                if (!entityExists) {
                        // Check to make sure key isn't used by another entity.
                        if (!isUniqueKey(em, entityKey)) {
                                throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.KeyExists", entityKey));
                        }
                }

                //was TODO validate "checked" categories or category groups (see section 5.2.3 of spec)? optional to support
                //at least one must be defined
                if (bindingTemplate.getAccessPoint() == null && bindingTemplate.getHostingRedirector() == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.bindingtemplate.NoAccessPoint"));
                }
                //but not both
                if (bindingTemplate.getAccessPoint() != null && bindingTemplate.getHostingRedirector() != null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.bindingtemplate.NoAccessPoint"));
                }
                validateCategoryBag(bindingTemplate.getCategoryBag(), config, false);
                validateTModelInstanceDetails(bindingTemplate.getTModelInstanceDetails(), config, false);
                validateAccessPoint(em, bindingTemplate.getAccessPoint(), config);
                validateDescriptions(bindingTemplate.getDescription());
                validateHostingRedirector(em, bindingTemplate.getHostingRedirector(), config);

                validateSignaturesBinding(bindingTemplate, config);
                //validateCheckedTModels(bindingTemplate, config);
        }

        public void validateTModel(EntityManager em, org.uddi.api_v3.TModel tModel, Configuration config, UddiEntityPublisher publisher) throws DispositionReportFaultMessage {
                // A supplied tModel can't be null
                if (tModel == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.tmodel.NullInput"));
                }

                boolean entityExists = false;
                String entityKey = tModel.getTModelKey();
                if (entityKey == null || entityKey.length() == 0) {
                        KeyGenerator keyGen = KeyGeneratorFactory.getKeyGenerator();
                        entityKey = keyGen.generate(publisher);
                        validateNotSigned(tModel);
                        tModel.setTModelKey(entityKey);
                } else {
                        // Per section 4.4: keys must be case-folded
                        entityKey = entityKey.toLowerCase();
                        tModel.setTModelKey(entityKey);

                        Object obj = em.find(org.apache.juddi.model.Tmodel.class, entityKey);
                        if (obj != null) {
                                entityExists = true;

                                // Make sure publisher owns this entity.
                                AccessCheck(obj, entityKey);
                                //if (!publisher.isOwner((UddiEntity) obj)&& !((Publisher) publisher).isAdmin()) {
                                //        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", entityKey));
                                // }
                        } else {
                                // Inside this block, we have a key proposed by the publisher on a new entity

                                // First test to see if this is a Key Generator tModel. The keyGenerator suffix appearing in the key is the indicator, since this is not
                                // allowed *unless* it's a key generator.
                                if (entityKey.toUpperCase().contains(KeyGenerator.KEYGENERATOR_SUFFIX.toUpperCase())) {
                                        ValidateUDDIKey.validateUDDIv3KeyGeneratorTModel(tModel);

                                        // The root publisher is only allowed one key generator.  This is published in the installation.
                                        String rootPublisherStr = "root";
                                        try {
                                                rootPublisherStr = AppConfig.getConfiguration().getString(Property.JUDDI_ROOT_PUBLISHER);
                                        } catch (ConfigurationException ce) {
                                                log.error("Could not read the root publisher setting in the configuration.");
                                        }
                                        if (publisher.getAuthorizedName().equals(rootPublisherStr)) {
                                                throw new FatalErrorException(new ErrorMessage("errors.tmodel.keygenerator.RootKeyGen"));
                                        }

                                        // It's a valid Key Generator, but is it available for this publisher?
                                        if (!publisher.isKeyGeneratorAvailable(em, entityKey)) {
                                                throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.BadPartition", entityKey));
                                        }

                                } else {
                                        // If not a key generator, then simply validate key and then check to see that the proposed key is valid for this publisher
                                        ValidateUDDIKey.validateUDDIv3Key(entityKey);
                                        //fix for JUDDI-851
                                        if (!entityKey.toUpperCase().startsWith("UUID:")) {
                                                if (!publisher.isValidPublisherKey(em, entityKey)) {
                                                        throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.BadPartition", entityKey));
                                                }
                                        }
                                }
                        }
                }

                if (!entityExists) {
                        // Check to make sure key isn't used by another entity.
                        if (!isUniqueKey(em, entityKey)) {
                                throw new KeyUnavailableException(new ErrorMessage("errors.keyunavailable.KeyExists", entityKey));
                        }
                }
                validateKeyLength(entityKey);

                // TODO: validate "checked" categories or category groups (see section 5.2.3 of spec)? optional to support
                if (tModel.getName() == null || tModel.getName().getValue() == null
                        || tModel.getName().getValue().equals("")) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.tmodel.NoName"));
                }

                validateCategoryBag(tModel.getCategoryBag(), config, false);
                validateIdentifierBag(tModel.getIdentifierBag(), config, false);
                validateDescriptions(tModel.getDescription());
                validateNameLength(tModel.getName().getValue());
                validateLang(tModel.getName().getLang());
                List<org.uddi.api_v3.OverviewDoc> overviewDocList = tModel.getOverviewDoc();
                if (overviewDocList != null) {
                        for (org.uddi.api_v3.OverviewDoc overviewDoc : overviewDocList) {
                                validateOverviewDoc(overviewDoc);
                        }
                }
                validateSignaturesTModel(tModel, config);

        }

        public void validatePublisherAssertion(EntityManager em, org.uddi.api_v3.PublisherAssertion pubAssertion) throws DispositionReportFaultMessage {
                // A supplied publisher assertion can't be null
                if (pubAssertion == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.pubassertion.NullInput"));
                }

                // The keyedRef must not be blank and every field must contain data.
                org.uddi.api_v3.KeyedReference keyedRef = pubAssertion.getKeyedReference();
                if (keyedRef == null
                        || keyedRef.getTModelKey() == null || keyedRef.getTModelKey().length() == 0
                        || keyedRef.getKeyName() == null || keyedRef.getKeyName().length() == 0
                        || keyedRef.getKeyValue() == null || keyedRef.getKeyValue().length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.pubassertion.BlankKeyedRef"));
                }

                String fromKey = pubAssertion.getFromKey();
                if (fromKey == null || fromKey.length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.pubassertion.BlankFromKey"));
                }

                String toKey = pubAssertion.getToKey();
                if (toKey == null || toKey.length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.pubassertion.BlankToKey"));
                }

                if (fromKey.equalsIgnoreCase(toKey)) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.pubassertion.SameBusinessKey"));
                }

                // Per section 4.4: keys must be case-folded
                fromKey = fromKey.toLowerCase();
                pubAssertion.setFromKey(fromKey);
                toKey = toKey.toLowerCase();
                pubAssertion.setToKey(toKey);
                validateKeyLength(toKey);
                validateKeyLength(fromKey);
                Object fromObj = em.find(org.apache.juddi.model.BusinessEntity.class, fromKey);
                if (fromObj == null) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.BusinessNotFound", fromKey));
                }

                Object toObj = em.find(org.apache.juddi.model.BusinessEntity.class, pubAssertion.getToKey());
                if (toObj == null) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.BusinessNotFound", toKey));
                }

                if (!publisher.isOwner((UddiEntity) fromObj) && !publisher.isOwner((UddiEntity) toObj)) {
                        throw new UserMismatchException(new ErrorMessage("errors.pubassertion.UserMismatch", fromKey + " & " + toKey));
                }

                try {
                        validateKeyedReference(pubAssertion.getKeyedReference(), AppConfig.getConfiguration(), false);
                } catch (ConfigurationException ce) {
                        log.error("Could not optain config. " + ce.getMessage(), ce);
                }
        }

        public void validateNames(List<org.uddi.api_v3.Name> names) throws DispositionReportFaultMessage {
                // At least one name is required
                if (names == null || names.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.names.NoInput"));
                }

                for (Name n : names) {
                        if (n.getValue() == null || n.getValue().length() == 0) {
                                throw new ValueNotAllowedException(new ErrorMessage("errors.names.NoValue"));
                        }
                        validateNameLength(n.getValue());
                        validateLang(n.getLang());
                }

        }

        public void validateContacts(org.uddi.api_v3.Contacts contacts, Configuration config) throws DispositionReportFaultMessage {
                // Contacts is optional
                if (contacts == null) {
                        return;
                }

                // If contacts do exist, at least one contact is required
                List<org.uddi.api_v3.Contact> contactList = contacts.getContact();
                if (contactList == null || contactList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.contacts.NoInput"));
                }

                for (org.uddi.api_v3.Contact contact : contactList) {
                        validateContact(contact, config);
                }

        }

        public void validateContact(org.uddi.api_v3.Contact contact, Configuration config) throws DispositionReportFaultMessage {
                if (log.isDebugEnabled()) {
                        log.debug("validateContact");
                }
                // A supplied contact can't be null
                if (contact == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.contact.NullInput"));
                }

                // At least one personName is required
                List<org.uddi.api_v3.PersonName> pnameList = contact.getPersonName();
                if (pnameList == null || pnameList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.contact.NoPersonName"));
                }
                for (org.uddi.api_v3.PersonName pn : pnameList) {
                        if (pn.getValue() == null || pn.getValue().length() == 0) {
                                throw new ValueNotAllowedException(new ErrorMessage("errors.contacts.NoPersonName"));
                        }
                        validateNameLength(pn.getValue());
                        validateLang(pn.getLang());
                }

                List<org.uddi.api_v3.Address> addressList = contact.getAddress();
                if (addressList != null) {
                        for (org.uddi.api_v3.Address address : addressList) {
                                if (address != null) {
                                        validateSortCode(address.getSortCode());
                                        validateKeyLength(address.getTModelKey());
                                        validateLang(address.getLang());
                                        validateUseType(address.getUseType());
                                        boolean checked = true;
                                        // Per section 4.4: keys must be case-folded
                                        if (address.getTModelKey() != null) {
                                                address.setTModelKey(address.getTModelKey().toLowerCase());
                                                validatedAddressLinesIfKeyDefined(address.getAddressLine());

                                                checked = verifyTModelKeyExistsAndChecked(address.getTModelKey(), config);

                                        }
                                        if (address.getAddressLine() == null || address.getAddressLine().size() == 0) {
                                                throw new ValueNotAllowedException(new ErrorMessage("errors.contact.NoAddressLine"));
                                        }

                                        if (checked) {
                                                validateAddressLines(address.getAddressLine(), config);
                                        }
                                }
                        }
                }
                validateEmailAddress(contact.getEmail());
                validatePhone(contact.getPhone());
                validateDescriptions(contact.getDescription());
                validateUseType(contact.getUseType());
        }

        public void validateDiscoveryUrls(org.uddi.api_v3.DiscoveryURLs discUrls) throws DispositionReportFaultMessage {
                // Discovery Urls is optional
                if (discUrls == null) {
                        return;
                }

                // If discUrls does exist, it must have at least one element
                List<org.uddi.api_v3.DiscoveryURL> discUrlList = discUrls.getDiscoveryURL();
                if (discUrlList == null || discUrlList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.discurls.NoInput"));
                }
                for (org.uddi.api_v3.DiscoveryURL url : discUrlList) {
                        if (url.getValue() == null || url.getValue().length() == 0) {
                                throw new ValueNotAllowedException(new ErrorMessage("errors.discurls.NoInput"));
                        }
                        validateDiscoveryUrlLength(url);
                }
        }

        public void validateCategoryBag(org.uddi.api_v3.CategoryBag categories, Configuration config, boolean isRoot) throws DispositionReportFaultMessage {

                // Category bag is optional
                if (categories == null) {
                        return;
                }

                // If category bag does exist, it must have at least one element
                List<KeyedReference> elems = categories.getKeyedReference();
                List<KeyedReferenceGroup> groups = categories.getKeyedReferenceGroup();
                if (groups.size() == 0 && elems.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.categorybag.NoInput"));
                }

                for (KeyedReferenceGroup group : groups) {
                        validateKeyedReferenceGroup(group, config, isRoot);
                }

                for (KeyedReference elem : elems) {
                        validateKeyedReference(elem, config, isRoot);
                }
        }

        public void validateIdentifierBag(org.uddi.api_v3.IdentifierBag identifiers, Configuration config, boolean isRoot) throws DispositionReportFaultMessage {

                // Identifier bag is optional
                if (identifiers == null) {
                        return;
                }

                // If category bag does exist, it must have at least one element
                List<org.uddi.api_v3.KeyedReference> keyedRefList = identifiers.getKeyedReference();
                if (keyedRefList == null || keyedRefList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.identifierbag.NoInput"));
                }

                for (org.uddi.api_v3.KeyedReference keyedRef : keyedRefList) {
                        validateKeyedReference(keyedRef, config, isRoot);
                }
        }

        public void validateKeyedReferenceGroup(KeyedReferenceGroup krg, Configuration config, boolean isRoot) throws DispositionReportFaultMessage {
                // Keyed reference groups must contain a tModelKey
                if (log.isDebugEnabled()) {
                        log.debug("validateKeyedReferenceGroup");
                }
                if (krg.getTModelKey() == null || krg.getTModelKey().length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.keyedreference.NoTModelKey"));
                }

                // Per section 4.4: keys must be case-folded
                String tmodelKey = krg.getTModelKey().toLowerCase();
                krg.setTModelKey(tmodelKey);
                validateKeyLength(tmodelKey);

                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (checkRef && !isRoot) {
                        this.verifyTModelKeyExists(tmodelKey);
                }

                boolean checked = verifyTModelKeyExistsAndChecked(tmodelKey, config);

                if (checked) {
                        List<KeyedReference> keyedRefs = krg.getKeyedReference();
                        // Should being empty raise an error?
                        if (keyedRefs != null && keyedRefs.size() > 0) {
                                for (KeyedReference keyedRef : keyedRefs) {
                                        validateKeyedReference(keyedRef, config, isRoot);
                                }
                        }
                }
        }

        /**
         *
         * @param kr
         * @param config
         * @param isRoot true during install time, otherwise false
         * @throws DispositionReportFaultMessage
         */
        public void validateKeyedReference(KeyedReference kr, Configuration config, boolean isRoot) throws DispositionReportFaultMessage {
                if (log.isDebugEnabled()) {
                        log.debug("validateKeyedReference");
                }
                String tmodelKey = kr.getTModelKey();

                if (tmodelKey == null || tmodelKey.length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.keyedreference.NoTModelKey"));
                }

                // Per section 4.4: keys must be case-folded
                tmodelKey = tmodelKey.toLowerCase();
                kr.setTModelKey(tmodelKey);
                validateKeyLength(tmodelKey);

                if (kr.getKeyValue() == null || kr.getKeyValue().length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.keyedreference.NoKeyValue"));
                }
                validateKeyValue(kr.getKeyValue());
                validateKeyName(kr.getKeyName());

                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (checkRef && !isRoot) {
                        this.verifyTModelKeyExists(tmodelKey);

                }

                String rootPublisherStr = config.getString(Property.JUDDI_ROOT_PUBLISHER);
                // Per section 6.2.2.1 of the specification, no publishers (except the root) are allowed to use the node categorization tmodelKey
                if (Constants.NODE_CATEGORY_TMODEL.equalsIgnoreCase(kr.getTModelKey())) {
                        if (!rootPublisherStr.equals(publisher.getAuthorizedName())) {
                                throw new ValueNotAllowedException(new ErrorMessage("errors.keyedreference.NodeCategoryTModel", Constants.NODE_CATEGORY_TMODEL));
                        }
                }
        }

        public void validateTModelInstanceDetails(org.uddi.api_v3.TModelInstanceDetails tmodelInstDetails, Configuration config, boolean isRoot) throws DispositionReportFaultMessage {
                if (log.isDebugEnabled()) {
                        log.debug("validateTModelInstanceDetails");
                }
                // tModel Instance Details is optional
                if (tmodelInstDetails == null) {
                        return;
                }

                // If tmodelInstDetails does exist, it must have at least one element
                List<org.uddi.api_v3.TModelInstanceInfo> tmodelInstInfoList = tmodelInstDetails.getTModelInstanceInfo();
                if (tmodelInstInfoList == null || tmodelInstInfoList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.tmodelinstdetails.NoInput"));
                }

                for (org.uddi.api_v3.TModelInstanceInfo tmodelInstInfo : tmodelInstInfoList) {
                        validateTModelInstanceInfo(tmodelInstInfo, config, isRoot);
                }
        }

        public void validateTModelInstanceInfo(org.uddi.api_v3.TModelInstanceInfo tmodelInstInfo, Configuration config, boolean isRoot) throws DispositionReportFaultMessage {
                // tModel Instance Info can't be null
                if (tmodelInstInfo == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.tmodelinstinfo.NullInput"));
                }

                // TModel key is required
                if (tmodelInstInfo.getTModelKey() == null || tmodelInstInfo.getTModelKey().length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.tmodelinstinfo.NoTModelKey"));
                }

                // Per section 4.4: keys must be case-folded
                tmodelInstInfo.setTModelKey((tmodelInstInfo.getTModelKey().toLowerCase()));

                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (checkRef && !isRoot) {
                        this.verifyTModelKeyExists(tmodelInstInfo.getTModelKey());
                }

                validateInstanceDetails(tmodelInstInfo.getInstanceDetails());
                if (log.isDebugEnabled()) {
                        log.debug("validateTModelInstanceInfo");
                }

                validateKeyLength(tmodelInstInfo.getTModelKey());
                validateDescriptions(tmodelInstInfo.getDescription());

        }

        public void validateInstanceDetails(org.uddi.api_v3.InstanceDetails instDetails) throws DispositionReportFaultMessage {
                // Instance Details is optional
                if (instDetails == null) {
                        return;
                }

                // At least one OverviewDoc or instanceParms must be supplied
                List<OverviewDoc> elems = instDetails.getOverviewDoc();
                if (instDetails.getInstanceParms() == null && elems.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.instdetails.NoOverviewOrParms"));
                }
                for (int i = 0; i < elems.size(); i++) {
                        validateDescriptions(elems.get(i).getDescription());
                        validateOverviewURL(elems.get(i).getOverviewURL());
                }
                if (instDetails.getInstanceParms()!=null){
                    if (instDetails.getInstanceParms().length()>8192){
                         throw new ValueNotAllowedException(new ErrorMessage("errors.instdetails.MaxLength",instDetails.getInstanceParms().length()+""));
                    }
                }
        }

        public void validateOverviewDoc(org.uddi.api_v3.OverviewDoc overviewDoc) throws DispositionReportFaultMessage {
                // OverviewDoc can't be null
                if (overviewDoc == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.overviewdoc.NullInput"));
                }

                // At least one description or overview URL must be supplied
                List<org.uddi.api_v3.Description> elems = overviewDoc.getDescription();
                if ((elems == null || elems.size() == 0) && overviewDoc.getOverviewURL() == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.overviewdoc.NoDescOrUrl"));
                }
                for (int i = 0; i < elems.size(); i++) {
                        validateLang(elems.get(i).getLang());
                        validateURL(elems.get(i).getValue());
                }
        }

        public void validateRegisteredInfo(org.uddi.api_v3.GetRegisteredInfo body) throws DispositionReportFaultMessage {
                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // infoSelection is required
                if (body.getInfoSelection() == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.getregisteredinfo.NoInfoSelection"));
                }

        }

        /**
         * Publishing API functions are specific to jUDDI. Requires
         * administrative privilege
         *
         * @param em
         * @param body
         * @throws DispositionReportFaultMessage
         */
        public void validateDeletePublisher(EntityManager em, DeletePublisher body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<String> entityKeyList = body.getPublisherId();
                if (entityKeyList == null || entityKeyList.size() == 0) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.NoKeys"));
                }

                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.deletepublisher.AdminReqd"));
                }

                HashSet<String> dupCheck = new HashSet<String>();
                for (String entityKey : entityKeyList) {
                        validateKeyLength(entityKey);
                        boolean inserted = dupCheck.add(entityKey);
                        if (!inserted) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.DuplicateKey", entityKey));
                        }

                        Object obj = em.find(org.apache.juddi.model.Publisher.class, entityKey);
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.PublisherNotFound", entityKey));
                        }

                }
        }

        public void validateSaveSubscriptionAdmin(EntityManager em, String publisherOrUsername, List<Subscription> subscriptions) throws DispositionReportFaultMessage {

                // No null input
                if (subscriptions == null || subscriptions.isEmpty()) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.deletepublisher.AdminReqd"));
                }
                UddiEntityPublisher user = new UddiEntityPublisher(publisherOrUsername);
                ValidateSubscription vsub = new ValidateSubscription(user);
                for (int i = 0; i < subscriptions.size(); i++) {
                        vsub.validateSubscriptions(em, subscriptions, user);
                }
        }

        public void validateSavePublisher(EntityManager em, SavePublisher body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<org.apache.juddi.api_v3.Publisher> entityList = body.getPublisher();
                if (entityList == null || entityList.size() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.savepublisher.NoInput"));
                }

                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.savepublisher.AdminReqd", publisher.getAuthorizedName()));
                }

                for (org.apache.juddi.api_v3.Publisher entity : entityList) {
                        validatePublisher(em, entity);
                }
        }

        public void validatePublisher(EntityManager em, org.apache.juddi.api_v3.Publisher publisher) throws DispositionReportFaultMessage {

                // No null input
                if (publisher == null) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.publisher.NullInput"));
                }

                String authorizedName = publisher.getAuthorizedName();
                if (authorizedName == null || authorizedName.length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.publisher.NoAuthorizedName"));
                }

                String publisherName = publisher.getPublisherName();
                if (publisherName == null || publisherName.length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.publisher.NoPublisherName"));
                }
//TODO identify JUDDI restrictions on publisher name
        }

        public void validateAdminDeleteTModel(EntityManager em, DeleteTModel body) throws DispositionReportFaultMessage {

                // No null input
                if (body == null) {
                        throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
                }

                // No null or empty list
                List<String> entityKeyList = body.getTModelKey();
                if (entityKeyList == null || entityKeyList.size() == 0) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.NoKeys"));
                }

                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
                }

                HashSet<String> dupCheck = new HashSet<String>();
                for (String entityKey : entityKeyList) {
                        validateKeyLength(entityKey);
                        boolean inserted = dupCheck.add(entityKey);
                        if (!inserted) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.DuplicateKey", entityKey));
                        }

                        //removed a check for checking if the entity exists which was moved to the juddi api class
                        //why? because we were looking up the same object twice in the database and its just not efficient
                }
        }
        ////////////////////////////////////////////////////////////////////
        ////////////////////////// begin validation code
        ////////////////////////////////////////////////////////////////////

        private static void validateDescription(String value) throws ValueNotAllowedException {
                if (value != null && value.length() > ValidationConstants.MAX_description) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.DescriptionTooLong"));
                }
        }

        public static void validateLang(String lang) throws ValueNotAllowedException {
                if (lang != null && lang.length() > ValidationConstants.MAX_xml_lang) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.names.LangTooLong"));
                }
        }

        private static void validateUseType(String useType) throws ValueNotAllowedException {
                if (useType != null && useType.length() > ValidationConstants.MAX_useType) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.names.UseTypeTooLong"));
                }
        }

        public static void validateKeyLength(String value) throws ValueNotAllowedException {
                if (value != null && value.length() > ValidationConstants.MAX_Key) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.keys.TooLong"));
                }
        }

        private void validateAccessPoint(EntityManager em, AccessPoint value, Configuration config) throws ValueNotAllowedException {
                if (log.isDebugEnabled()) {
                        log.debug("validateAccessPoint");
                }

                if (value != null) {
                        if (value.getValue().length() > ValidationConstants.MAX_accessPoint) {
                                throw new ValueNotAllowedException(new ErrorMessage("errors.accessPoint.TooLong"));
                        }

                        validateUseType(value.getUseType());
                        if (value.getUseType() != null) {
                                if (value.getUseType().equalsIgnoreCase(AccessPointType.BINDING_TEMPLATE.toString())) {
                                        //validate that the referenced binding key exists already
                                        Object obj = em.find(org.apache.juddi.model.BindingTemplate.class, value.getValue());
                                        if (obj == null) {
                                                throw new ValueNotAllowedException(new ErrorMessage("errors.accessPoint.bindingtemplateRedirect.keynotexist"));
                                        }

                                } else if (value.getUseType().equalsIgnoreCase(AccessPointType.HOSTING_REDIRECTOR.toString())) {
                                        try {
                                                //no validation necessary other than confirm that it's a URL
                                                new URL(value.getValue());
                                        } catch (MalformedURLException ex) {
                                                throw new ValueNotAllowedException(new ErrorMessage("errors.accessPoint.hostingRedirector.notaurl"));
                                        }
                                }
                                //TODO determine if additional validation is required.
                                //potentials, if its a wsdl deployment, is the Value a valid URI
                                //if endpoint, is it a valid URI?
                        }
                }
        }

        private void validateHostingRedirector(EntityManager em, HostingRedirector hostingRedirector, Configuration config) throws ValueNotAllowedException {
                if (log.isDebugEnabled()) {
                        log.debug("validateHostingRedirector");
                }
                if (hostingRedirector == null) {
                        return;
                }

                if (hostingRedirector.getBindingKey() == null || hostingRedirector.getBindingKey().length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.hostingredirector.noinput"));
                }
                if (hostingRedirector.getBindingKey().length() > ValidationConstants.MAX_Key) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.hostingredirector.TooLong"));
                }
                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (checkRef) {
                        //TODO check the spec to confirm this is logically correct
            /*Object obj = em.find(org.apache.juddi.model.BindingTemplate.class, hostingRedirector.getBindingKey());
                         if (obj == null) {
                         throw new ValueNotAllowedException(new ErrorMessage("errors.hostingredirector.keynotexist"));
                         }*/
                }

        }

        private void validateNameLength(String value) throws ValueNotAllowedException {
                if (value == null || value.length() == 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.names.NoInput"));
                }
                if (value.length() > ValidationConstants.MAX_name) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.names.TooLong"));
                }

        }

        private void validateSortCode(String value) throws ValueNotAllowedException {
                if (value != null && value.length() > ValidationConstants.MAX_sortCode) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.sortCode.TooLong"));
                }
        }

        private void validateAddressLines(List<AddressLine> addressLine, Configuration config) throws ValueNotAllowedException {
                if (log.isDebugEnabled()) {
                        log.debug("validateAddressLines");
                }
                if (addressLine != null) {
                        for (int i = 0; i < addressLine.size(); i++) {
                                validateKeyName(addressLine.get(i).getKeyName());
                                verifyTModelKeyExistsAndChecked(addressLine.get(i).getKeyName(), config);

                                validateKeyValue(addressLine.get(i).getKeyValue());
                                if (addressLine.get(i).getValue() == null || addressLine.get(i).getValue().length() == 0) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.addressline.noinput"));
                                }
                                if (addressLine.get(i).getValue().length() > ValidationConstants.MAX_addressLine) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.addressline.TooLong"));
                                }
                        }
                }
        }

        private void validateEmailAddress(List<Email> email) throws ValueNotAllowedException {
                if (email != null) {
                        for (int i = 0; i < email.size(); i++) {
                                validateUseType(email.get(i).getUseType());
                                if (email.get(i).getValue() == null || email.get(i).getValue().length() == 0) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.email.noinput"));
                                }
                                if (email.get(i).getValue().length() > ValidationConstants.MAX_email) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.email.TooLong"));
                                }
                        }
                }
        }

        private void validatePhone(List<Phone> phone) throws ValueNotAllowedException {
                if (phone != null) {
                        for (int i = 0; i < phone.size(); i++) {
                                validateUseType(phone.get(i).getUseType());
                                if (phone.get(i).getValue() == null
                                        || phone.get(i).getValue().length() == 0) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.phone.noinput"));
                                }
                                if (phone.get(i).getValue().length() > ValidationConstants.MAX_phone) {
                                        throw new ValueNotAllowedException(new ErrorMessage("errors.phone.TooLong"));
                                }
                        }
                }
        }

        private void validateDiscoveryUrlLength(DiscoveryURL url) throws ValueNotAllowedException {
                if (url != null) {
                        validateUseType(url.getUseType());
                        validateURL(url.getValue());
                }
        }

        private void validateKeyValue(String value) throws ValueNotAllowedException {
                if (value != null && value.length() > ValidationConstants.MAX_keyValue) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.keyvalue.TooLong"));
                }
        }

        private void validateKeyName(String value) throws ValueNotAllowedException {
                if (value != null && value.length() > ValidationConstants.MAX_keyValue) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.keyname.TooLong"));
                }

        }

        private void validateDescriptions(List<Description> description) throws ValueNotAllowedException {
                for (int i = 0; i < description.size(); i++) {
                        if (description.get(i).getValue() == null) {
                                throw new ValueNotAllowedException(new ErrorMessage("errors.contact.EmptyDescription"));
                        }

                        validateLang(description.get(i).getLang());
                        validateDescription(description.get(i).getValue());
                }
        }

        private void validateOverviewURL(OverviewURL overviewURL) throws ValueNotAllowedException {
                if (overviewURL != null) {
                        validateUseType(overviewURL.getUseType());
                        validateURL(overviewURL.getValue());
                }
        }

        private void validateURL(String value) throws ValueNotAllowedException {
                if (value != null && value.length() > ValidationConstants.MAX_overviewURL) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.url.overviewTooLong"));
                }
        }

        /**
         * Validates that a tmodel key is registered Alex O'Ree
         *
         * @param tmodelKey
         * @param em
         * @throws ValueNotAllowedException
         * @see org.apache.juddi.config.Install
         * @since 3.1.5
         */
        private boolean verifyTModelKeyExistsAndChecked(String tmodelKey, Configuration config) throws ValueNotAllowedException {
                boolean checked = true;
                if (tmodelKey == null || tmodelKey.length() == 0) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:categorization:types")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:categorization:nodes")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:v3_inquiry")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:v3_publication")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:v3_security")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:v3_ownership_transfer")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:v3_subscription")) {
                        return false;
                }
                if (tmodelKey.equalsIgnoreCase("uddi:uddi.org:v3_subscriptionlistener")) {
                        return false;
                }

                if (config == null) {
                        log.warn(new ErrorMessage("errors.tmodel.ReferentialIntegrityNullConfig"));
                        return false;
                }
                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (checkRef) {
                        if (log.isDebugEnabled()) {
                                log.debug("verifyTModelKeyExists " + tmodelKey);
                        }
                        EntityManager em = PersistenceManager.getEntityManager();

                        if (em == null) {
                                //this is normally the Install class firing up
                                log.warn(new ErrorMessage("errors.tmodel.ReferentialIntegrityNullEM"));
                        } else {
                                //Collections.sort(buildInTmodels);
                                //if ((buildInTmodels, tmodelKey) == -1)
                                Tmodel modelTModel = null;
                                {
                                        EntityTransaction tx = em.getTransaction();
                                        try {

                                                tx.begin();
                                                modelTModel = em.find(org.apache.juddi.model.Tmodel.class, tmodelKey);

                                                if (modelTModel == null) {
                                                        checked = false;
                                                } else {
                                                     if (modelTModel.getCategoryBag()!=null)
                                                        for (org.apache.juddi.model.KeyedReference ref : modelTModel.getCategoryBag().getKeyedReferences()) {
                                                                if ("uddi-org:types:unchecked".equalsIgnoreCase(ref.getKeyName())) {
                                                                        checked = false;
                                                                        break;
                                                                }
                                                        }
                                                }

                                                tx.commit();

                                        } finally {
                                                if (tx.isActive()) {
                                                        tx.rollback();
                                                }
                                                em.close();
                                        }
                                        if (modelTModel == null) {
                                                throw new ValueNotAllowedException(new ErrorMessage("errors.tmodel.ReferencedKeyDoesNotExist", tmodelKey));
                                        }
                                }
                        }
                }
                return checked;
        }

        private boolean verifyTModelKeyChecked(Tmodel modelTModel) {
                boolean checked = true;
                if (modelTModel == null) {
                        checked = false;
                } else {
                        for (org.apache.juddi.model.KeyedReference ref : modelTModel.getCategoryBag().getKeyedReferences()) {
                                if ("uddi-org:types:unchecked".equalsIgnoreCase(ref.getTmodelKeyRef())) {
                                        checked = false;
                                        break;
                                }
                        }
                }
                return checked;
        }

        /**
         * throws if it doesn't exist, returns it if it does
         *
         * @param tmodelKey
         * @return null, or a TModel object
         * @throws ValueNotAllowedException
         * @since 3.3
         */
        private TModel verifyTModelKeyExists(String tmodelKey) throws ValueNotAllowedException, DispositionReportFaultMessage {
                TModel api = null;
                EntityManager em = PersistenceManager.getEntityManager();
                boolean found = false;
                if (em == null) {
                        log.warn(new ErrorMessage("errors.tmodel.ReferentialIntegrityNullEM"));
                } else {
                        Tmodel modelTModel = null;
                        {
                                EntityTransaction tx = em.getTransaction();
                                try {

                                        tx.begin();
                                        modelTModel = em.find(org.apache.juddi.model.Tmodel.class, tmodelKey);

                                        if (modelTModel != null) {
                                                found = true;
                                                api = new TModel();
                                                MappingModelToApi.mapTModel(modelTModel, api);
                                        }
                                        tx.commit();

                                } finally {
                                        if (tx.isActive()) {
                                                tx.rollback();
                                        }
                                        em.close();
                                }

                        }
                }
                if (!found) {
                        throw new ValueNotAllowedException(new ErrorMessage("errors.tmodel.ReferencedKeyDoesNotExist", tmodelKey));
                }
                return api;
        }

        private List<String> GetBindingKeysCheckedTModelKeyedReferenceBT(Map<String, TModel> cache, List<BindingTemplate> obj) {
                List<String> ret = new ArrayList<String>();

                if (obj == null) {
                        return ret;
                }
                for (BindingTemplate bt : obj) {
                        if (bt.getCategoryBag() != null) {
                                for (int i = 0; i < bt.getCategoryBag().getKeyedReference().size(); i++) {
                                        ret.addAll(GetBindingKeysCheckedTModelKeyedReference(cache, bt.getCategoryBag().getKeyedReference().get(i)));
                                }
                        }
                }

                return ret;
        }

        private List<String> GetBindingKeysCheckedTModelKeyedReferenceBS(Map<String, TModel> cache, List<BusinessService> obj) {
                List<String> ret = new ArrayList<String>();

                if (obj == null) {
                        return ret;
                }
                for (BusinessService bt : obj) {
                        if (bt.getCategoryBag() != null) {
                                for (int i = 0; i < bt.getCategoryBag().getKeyedReference().size(); i++) {
                                        ret.addAll(GetBindingKeysCheckedTModelKeyedReference(cache, bt.getCategoryBag().getKeyedReference().get(i)));
                                }
                        }
                        if (bt.getBindingTemplates() != null) {
                                ret.addAll(GetBindingKeysCheckedTModelKeyedReferenceBT(cache, bt.getBindingTemplates().getBindingTemplate()));
                        }
                }

                return ret;
        }

        private List<String> GetBindingKeysCheckedTModelKeyedReferenceBE(Map<String, TModel> cache, List<BusinessEntity> obj) {
                List<String> ret = new ArrayList<String>();

                if (obj == null) {
                        return ret;
                }
                for (BusinessEntity bt : obj) {
                        if (bt.getCategoryBag() != null) {
                                for (int i = 0; i < bt.getCategoryBag().getKeyedReference().size(); i++) {
                                        ret.addAll(GetBindingKeysCheckedTModelKeyedReference(cache, bt.getCategoryBag().getKeyedReference().get(i)));
                                }
                        }
                        if (bt.getIdentifierBag() != null) {
                                for (int i = 0; i < bt.getIdentifierBag().getKeyedReference().size(); i++) {
                                        ret.addAll(GetBindingKeysCheckedTModelKeyedReference(cache, bt.getIdentifierBag().getKeyedReference().get(i)));
                                }
                        }

                        if (bt.getBusinessServices() != null) {
                                ret.addAll(GetBindingKeysCheckedTModelKeyedReferenceBS(cache, bt.getBusinessServices().getBusinessService()));
                        }
                }
                return ret;
        }

        private List<String> GetBindingKeysCheckedTModelKeyedReferenceTM(Map<String, TModel> cache, List<TModel> obj) {
                List<String> ret = new ArrayList<String>();

                if (obj == null) {
                        return ret;
                }
                for (TModel bt : obj) {
                        if (bt.getCategoryBag() != null) {
                                for (int i = 0; i < bt.getCategoryBag().getKeyedReference().size(); i++) {
                                        ret.addAll(GetBindingKeysCheckedTModelKeyedReference(cache, bt.getCategoryBag().getKeyedReference().get(i)));
                                }
                        }
                        if (bt.getIdentifierBag() != null) {
                                for (int i = 0; i < bt.getIdentifierBag().getKeyedReference().size(); i++) {
                                        ret.addAll(GetBindingKeysCheckedTModelKeyedReference(cache, bt.getIdentifierBag().getKeyedReference().get(i)));
                                }
                        }
                }
                return ret;
        }

        /**
         * this should return a list of binding keys, only if the referenced kr
         * contains is validated by
         *
         * @param cache
         * @param get
         * @return
         */
        private List<String> GetBindingKeysCheckedTModelKeyedReference(Map<String, TModel> cache, KeyedReference get) {
                List<String> ret = new ArrayList<String>();
                TModel ref = null;
                log.debug("looking for is validated by for keyedref " + get.getTModelKey());
                if (cache.containsKey(get.getTModelKey())) {
                        ref = cache.get(get.getTModelKey());
                }
                if (ref == null) {
                        try {
                                ref = verifyTModelKeyExists(get.getTModelKey());
                                cache.put(get.getTModelKey(), ref);
                        } catch (Exception ex) {
                                log.error("unexpected error loading tmodel " + get.getTModelKey(), ex);
                        }
                }
                if (ref != null) {

                        ret.addAll(TModelContains(UDDIConstants.IS_VALIDATED_BY, ref));
                        ret.addAll(TModelContains(UDDIConstantsV2.IS_VALIDATED_BY, ref));

                }
                return ret;
        }

        /**
         * returns all keyvalues from ref.catbag and identbag where the tmodel
         * key matches
         *
         * @param key
         * @param ref
         * @return
         */
        private List<String> TModelContains(String key, TModel ref) {

                if (key == null) {
                        return null;
                }
                if (ref == null || ref.getTModelKey()==null) {
                        return null;
                }
                log.debug("looking for key=" + key + " from tModel " + ref.getTModelKey());
                List<String> ret = new ArrayList<String>();
                
                if (ref.getCategoryBag() != null) {
                        for (int i = 0; i < ref.getCategoryBag().getKeyedReference().size(); i++) {
                                if (ref.getCategoryBag().getKeyedReference().get(i).getTModelKey().equalsIgnoreCase(key)) {
                                        log.debug("found reference for key=" + key + " from tModel " + ref.getTModelKey() + " validation endpoint " + ref.getCategoryBag().getKeyedReference().get(i).getKeyValue());
                                        ret.add(ref.getCategoryBag().getKeyedReference().get(i).getKeyValue());
                                }
                        }
                        for (int i = 0; i < ref.getCategoryBag().getKeyedReferenceGroup().size(); i++) {
                                for (int k = 0; k < ref.getCategoryBag().getKeyedReferenceGroup().get(i).getKeyedReference().size(); k++) {
                                        if (ref.getCategoryBag().getKeyedReferenceGroup().get(i).getKeyedReference().get(k).getTModelKey().equalsIgnoreCase(key)) {
                                                log.debug("found reference for key=" + key + " from tModel " + ref.getTModelKey() + " validation endpoint " + ref.getCategoryBag().getKeyedReferenceGroup().get(i).getKeyedReference().get(k).getKeyValue());
                                                ret.add(ref.getCategoryBag().getKeyedReferenceGroup().get(i).getKeyedReference().get(k).getKeyValue());
                                        }
                                }
                        }
                }
                if (ref.getIdentifierBag() != null) {
                        for (int i = 0; i < ref.getIdentifierBag().getKeyedReference().size(); i++) {
                                if (ref.getIdentifierBag().getKeyedReference().get(i).getTModelKey().equalsIgnoreCase(key)) {
                                        log.debug("found reference for key=" + key + " from tModel " + ref.getTModelKey() + " validation endpoint " + ref.getIdentifierBag().getKeyedReference().get(i).getKeyValue());
                                        ret.add(ref.getIdentifierBag().getKeyedReference().get(i).getKeyValue());
                                }
                        }
                }
                return ret;
        }

        /**
         * JUDDI-849 Each addressLine element MAY be adorned with two optional
         * descriptive attributes, keyName and keyValue. Both attributes MUST be
         * present in each address line if a tModelKey is specified in the
         * address structure. When no tModelKey is provided for the address
         * structure, the keyName and keyValue attributes have no defined
         * meaning.
         *
         * @param addressLine
         */
        private void validatedAddressLinesIfKeyDefined(List<AddressLine> addressLine) throws ValueNotAllowedException {
                StringBuilder err = new StringBuilder();
                for (int i = 0; i < addressLine.size(); i++) {

                        if (addressLine.get(i).getKeyName() == null
                                || addressLine.get(i).getKeyName().trim().length() == 0) {
                                err.append("addressLine(").append(i).append(").keyName,");
                        }
                        if (addressLine.get(i).getKeyValue() == null
                                || addressLine.get(i).getKeyValue().trim().length() == 0) {
                                err.append("addressLine(").append(i).append(").keyValue,");
                        }
                        if (addressLine.get(i).getValue() == null
                                || addressLine.get(i).getValue().trim().length() == 0) {
                                 err.append("addressLine(").append(i).append(").value,");
                        }
                }
                if (err.length() > 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("E_invalidValueAddressLine", err.toString()));
                }
        }

        private void validateCheckedTModelsBT(List<BindingTemplate> bindingTemplate, Configuration config) throws ValueNotAllowedException {

                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }

                if (!checkRef) {
                        return;
                }
                Map<String, TModel> cache = new HashMap<String, TModel>();
                List<String> bindings = GetBindingKeysCheckedTModelKeyedReferenceBT(cache, bindingTemplate);

                if (!bindings.isEmpty()) {
                        //get a unique list
                        bindings = new ArrayList(new HashSet(bindings));
                        for (int i = 0; i < bindings.size(); i++) {
                                //load binding from database
                                EntityManager em = PersistenceManager.getEntityManager();
                                org.apache.juddi.model.BindingTemplate find = em.find(org.apache.juddi.model.BindingTemplate.class, bindings.get(i));
                                if (find != null) {
                                        //parse endpoint
                                        String url = find.getAccessPointUrl();
                                        if (url == null) {
                                                url = find.getHostingRedirector();
                                        }
                                        if (url != null) {
                                                //call ValidateValuesFromWebService
                                                //optimization for localhost?
                                                ValidateValuesFromWebService.ValidateBinding(Rectify(url, config), bindingTemplate);
                                        }

                                }
                        }
                }
        }

        private void validateCheckedTModelsBS(List<BusinessService> bizlist, Configuration config) throws ValueNotAllowedException {
                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (!checkRef) {
                        return;
                }
                Map<String, TModel> cache = new HashMap<String, TModel>();
                List<String> bindings = GetBindingKeysCheckedTModelKeyedReferenceBS(cache, bizlist);

                if (!bindings.isEmpty()) {
                        //get a unique list
                        bindings = new ArrayList(new HashSet(bindings));
                        for (int i = 0; i < bindings.size(); i++) {
                                //load binding from database
                                EntityManager em = PersistenceManager.getEntityManager();
                                org.apache.juddi.model.BindingTemplate find = em.find(org.apache.juddi.model.BindingTemplate.class, bindings.get(i));
                                if (find != null) {
                                        //parse endpoint
                                        String url = find.getAccessPointUrl();
                                        if (url == null) {
                                                url = find.getHostingRedirector();
                                        }
                                        if (url != null) {
                                                //call ValidateValuesFromWebService
                                                //optimization for localhost?
                                                ValidateValuesFromWebService.ValidateService(Rectify(url, config), bizlist);
                                        }

                                }
                        }
                }
        }

        private void validateCheckedTModelsBE(List<BusinessEntity> entity, Configuration config) throws ValueNotAllowedException {
                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (!checkRef) {
                        return;
                }
                Map<String, TModel> cache = new HashMap<String, TModel>();
                List<String> bindings = GetBindingKeysCheckedTModelKeyedReferenceBE(cache, entity);

                if (!bindings.isEmpty()) {
                        //get a unique list
                        bindings = new ArrayList(new HashSet(bindings));
                        for (int i = 0; i < bindings.size(); i++) {
                                //load binding from database
                                EntityManager em = PersistenceManager.getEntityManager();
                                org.apache.juddi.model.BindingTemplate find = em.find(org.apache.juddi.model.BindingTemplate.class, bindings.get(i));
                                if (find != null) {
                                        //parse endpoint
                                        String url = find.getAccessPointUrl();
                                        if (url == null) {
                                                url = find.getHostingRedirector();
                                        }
                                        if (url != null) {
                                                //call ValidateValuesFromWebService
                                                //optimization for localhost?
                                                ValidateValuesFromWebService.ValidateBusiness(Rectify(url, config), entity);
                                        }

                                }
                        }
                }
        }

        private void validateCheckedTModelsTM(List<TModel> entity, Configuration config) throws ValueNotAllowedException {
                boolean checkRef = false;
                try {
                        checkRef = config.getBoolean(Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY, false);
                } catch (Exception ex) {
                        log.warn("Error caught reading " + Property.JUDDI_ENFORCE_REFERENTIAL_INTEGRITY + " from config file", ex);
                }
                if (!checkRef) {
                        return;
                }
                Map<String, TModel> cache = new HashMap<String, TModel>();
                List<String> bindings = GetBindingKeysCheckedTModelKeyedReferenceTM(cache, entity);

                if (!bindings.isEmpty()) {
                        //get a unique list
                        bindings = new ArrayList(new HashSet(bindings));
                        for (int i = 0; i < bindings.size(); i++) {
                                //load binding from database
                                EntityManager em = PersistenceManager.getEntityManager();
                                org.apache.juddi.model.BindingTemplate find = em.find(org.apache.juddi.model.BindingTemplate.class, bindings.get(i));
                                if (find != null) {
                                        //parse endpoint
                                        String url = find.getAccessPointUrl();
                                        if (url == null) {
                                                url = find.getHostingRedirector();
                                        }
                                        if (url != null) {
                                                log.debug("attempting vsv from " + url);
                                                //call ValidateValuesFromWebService
                                                //optimization for localhost?
                                                ValidateValuesFromWebService.ValidateTModel(Rectify(url, config), entity);
                                        }

                                }
                        }
                }
        }

        private String Rectify(String url, Configuration config) {
                //${juddi.server.baseurl}
                Properties p = new Properties();
                p.put("juddi.server.baseurl", config.getString("juddi.server.baseurl", Property.DEFAULT_BASE_URL));

                return TokenResolver.replaceTokens(url, p);
        }

        public void validateDeleteNode(EntityManager em, DeleteNode nodeID, ReplicationConfiguration cfg) throws DispositionReportFaultMessage {
                if (nodeID == null) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteClerk.NoInput"));
                }
                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.deletepublisher.AdminReqd"));
                }
                if (nodeID.getNodeID() == null || nodeID.getNodeID().trim().equalsIgnoreCase("")) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteNode.NoInput"));
                }
                //get the latest replication config
                if (cfg != null) {
                        if (cfg.getCommunicationGraph() != null) {
                                for (String node : cfg.getCommunicationGraph().getNode()) {
                                        if (node.equals(nodeID.getNodeID())) {
                                                throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteNode.InReplicationConfig", nodeID.getNodeID()));
                                        }
                                }
                                for (int i = 0; i < cfg.getCommunicationGraph().getEdge().size(); i++) {
                                        if (nodeID.getNodeID().equals(cfg.getCommunicationGraph().getEdge().get(i).getMessageReceiver())) {
                                                throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteNode.InReplicationConfig", nodeID.getNodeID()));
                                        }
                                        if (nodeID.getNodeID().equals(cfg.getCommunicationGraph().getEdge().get(i).getMessageSender())) {
                                                throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteNode.InReplicationConfig", nodeID.getNodeID()));
                                        }

                                }
                        }
                }

        }

        public void validateDeleteClerk(EntityManager em, DeleteClerk clerkID) throws DispositionReportFaultMessage {
                if (clerkID == null) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteClerk.NoInput"));
                }
                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.deletepublisher.AdminReqd"));
                }
                if (clerkID.getClerkID() == null || clerkID.getClerkID().trim().equalsIgnoreCase("")) {
                        throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteClerk.NoInput"));
                }

        }

        public void validateGetAllNodes() throws DispositionReportFaultMessage {
                if (!((Publisher) publisher).isAdmin()) {
                        throw new UserMismatchException(new ErrorMessage("errors.deletepublisher.AdminReqd"));
                }
        }

       private org.apache.juddi.v3.client.cryptor.DigSigUtil ds = null;

        private synchronized void initDigSig(Configuration config) {
                if (ds == null) {
                        
                        Properties p = new Properties();
                        /**
                         * <trustStorePath>truststore.jks</trustStorePath>
                         * <trustStoreType>JKS</trustStoreType>
                         * <trustStorePassword
                         * isPasswordEncrypted="false"
                         * cryptoProvider="org.apache.juddi.v3.client.crypto.AES128Cryptor">password</trustStorePassword>
                         *
                         * <checkTimestamps>true</checkTimestamps>
                         * <checkTrust>true</checkTrust>
                         * <checkRevocationCRL>true</checkRevocationCRL>
                         */
                        p.put(DigSigUtil.TRUSTSTORE_FILE, config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePath", ""));
                        p.put(DigSigUtil.TRUSTSTORE_FILETYPE, config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStoreType", ""));

                        String enc = config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePassword", "");
                        if (config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePassword[@isPasswordEncrypted]", false)) {
                                log.debug("trust password is encrypted, decrypting...");
                                
                                String prov = config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePassword[@cryptoProvider]", "");
                                try {
                                        p.setProperty(DigSigUtil.TRUSTSTORE_FILE_PASSWORD, CryptorFactory.getCryptor(prov).decrypt(enc));
                                } catch (Exception ex) {
                                        log.warn("unable to decrypt trust store password " + ex.getMessage());
                                        log.debug("unable to decrypt trust store password " + ex.getMessage(), ex);
                                }

                        } else if (!"".equals(enc)){
                                log.warn("Hey, you should consider encrypting your trust store password!");
                                p.setProperty(DigSigUtil.TRUSTSTORE_FILE_PASSWORD, enc);
                        }

                        p.put(DigSigUtil.CHECK_REVOCATION_STATUS_CRL, config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "checkRevocationCRL", "true"));
                        p.put(DigSigUtil.CHECK_TRUST_CHAIN, config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "checkTrust", "true"));
                        p.put(DigSigUtil.CHECK_TIMESTAMPS, config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "checkTimestamps", "true"));

                        try {
                                ds = new DigSigUtil(p);
                        } catch (CertificateException ex) {
                                log.error("", ex);
                        }
                        //System.out.println("loaded from " + AppConfig.getConfigFileURL());
                        //p.list(System.out);
                }
        }

        private void validateSignaturesBinding(BindingTemplate bindingTemplate, Configuration config) throws FatalErrorException {
                boolean shouldcheck = config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_ENABLE, false);
                initDigSig(config);
                if (shouldcheck && !bindingTemplate.getSignature().isEmpty() && ds != null) {
                        AtomicReference<String> outmsg = new AtomicReference<String>();
                        boolean ok = ds.verifySignedUddiEntity(bindingTemplate, outmsg);
                        if (!ok) {
                                throw new FatalErrorException(new ErrorMessage("errors.digitalsignature.validationfailure", bindingTemplate.getBindingKey() + " " + outmsg.get()));
                        }

                }
        }

        private void validateSignaturesService(BusinessService businessService, Configuration config) throws FatalErrorException {
                boolean shouldcheck = config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_ENABLE, false);
                initDigSig(config);
                if (shouldcheck && !businessService.getSignature().isEmpty() && ds != null) {
                        AtomicReference<String> outmsg = new AtomicReference<String>();
                        boolean ok = ds.verifySignedUddiEntity(businessService, outmsg);
                        if (!ok) {
                                throw new FatalErrorException(new ErrorMessage("errors.digitalsignature.validationfailure", businessService.getServiceKey() + " " + outmsg.get()));
                        }

                }
        }

        private void validateSignaturesTModel(TModel tModel, Configuration config) throws FatalErrorException {
                boolean shouldcheck = config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_ENABLE, false);
                initDigSig(config);
                if (shouldcheck && !tModel.getSignature().isEmpty() && ds != null) {
                        AtomicReference<String> outmsg = new AtomicReference<String>();
                        boolean ok = ds.verifySignedUddiEntity(tModel, outmsg);
                        if (!ok) {
                                throw new FatalErrorException(new ErrorMessage("errors.digitalsignature.validationfailure", tModel.getTModelKey() + " " + outmsg.get()));
                        }

                }
        }

        private void validateSignaturesBusiness(BusinessEntity businessEntity, Configuration config) throws FatalErrorException {
                boolean shouldcheck = config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_ENABLE, false);
                initDigSig(config);
                if (shouldcheck && !businessEntity.getSignature().isEmpty() && ds != null) {
                        AtomicReference<String> outmsg = new AtomicReference<String>();
                        boolean ok = ds.verifySignedUddiEntity(businessEntity, outmsg);
                        if (!ok) {
                                throw new FatalErrorException(new ErrorMessage("errors.digitalsignature.validationfailure", businessEntity.getBusinessKey() + " " + outmsg.get()));
                        }

                }
        }

}
