/*
 * 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.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;

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.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 {

        /**
         * This flag will add additional output to stdout for debugging
         * purposes, set this to true if
         */
        private Log log = LogFactory.getLog(this.getClass());

        /**
         * 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)) {
                        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()));
                                }

                        }

                }
        }

        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);

        }

        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);
                }

        }

        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);

                //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);
                        }
                }

        }

        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());
                }
        }

        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));
                        }

                        Object obj = em.find(org.apache.juddi.model.Tmodel.class, entityKey);
                        if (obj == null) {
                                throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.TModelNotFound", entityKey));
                        }

                        //if (!publisher.isOwner((UddiEntity) obj)) {
                        //        throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", entityKey));
                        //}
                }
        }
        ////////////////////////////////////////////////////////////////////
        ////////////////////////// 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 {
                                                        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) {

                log.debug("looking for key=" + key + " from tModel " + ref.getTModelKey());
                List<String> ret = new ArrayList<String>();
                if (ref == null) {
                        return null;
                }
                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 {
                String err = "";
                for (int i = 0; i < addressLine.size(); i++) {

                        if (addressLine.get(i).getKeyName() == null
                                || addressLine.get(i).getKeyName().trim().length() == 0) {
                                err += "addressLine(" + i + ").keyName,";
                        }
                        if (addressLine.get(i).getKeyValue() == null
                                || addressLine.get(i).getKeyValue().trim().length() == 0) {
                                err += "addressLine(" + i + ").keyValue,";
                        }
                        if (addressLine.get(i).getValue() == null
                                || addressLine.get(i).getValue().trim().length() == 0) {
                                err += "addressLine(" + i + ").value,";
                        }
                }
                if (err.length() > 0) {
                        throw new ValueNotAllowedException(new ErrorMessage("E_invalidValueAddressLine", err));
                }
        }

        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"));
                }
        }

}
