<commit_before>/*
 * Copyright 2007-2008 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 *
 * 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.kuali.rice.kim.impl.type;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.kuali.rice.core.api.util.ClassLoaderUtils;
import org.kuali.rice.core.api.util.RiceKeyConstants;
import org.kuali.rice.core.api.util.type.TypeUtils;
import org.kuali.rice.core.web.format.Formatter;
import org.kuali.rice.kew.doctype.bo.DocumentType;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;
import org.kuali.rice.kim.api.type.KimType;
import org.kuali.rice.kim.api.type.KimTypeAttribute;
import org.kuali.rice.kim.api.type.KimTypeInfoService;
import org.kuali.rice.kim.api.type.KimTypeService;
import org.kuali.rice.kim.bo.types.dto.AttributeDefinitionMap;
import org.kuali.rice.kns.lookup.LookupUtils;
import org.kuali.rice.kns.util.FieldUtils;
import org.kuali.rice.kns.web.ui.Field;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.comparator.StringValueComparator;
import org.kuali.rice.krad.datadictionary.AttributeDefinition;
import org.kuali.rice.krad.datadictionary.KimAttributeDefinition;
import org.kuali.rice.krad.datadictionary.KimDataDictionaryAttributeDefinition;
import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
import org.kuali.rice.krad.datadictionary.validation.ValidationPattern;
import org.kuali.rice.krad.keyvalues.KimAttributeValuesFinder;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DataDictionaryService;
import org.kuali.rice.krad.service.DictionaryValidationService;
import org.kuali.rice.krad.service.KRADServiceLocator;
import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
import org.kuali.rice.krad.util.ErrorMessage;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADUtils;
import org.kuali.rice.krad.util.ObjectUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

public class KimTypeServiceBase implements KimTypeService {

	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KimTypeServiceBase.class);

	private BusinessObjectService businessObjectService;
	private DictionaryValidationService dictionaryValidationService;
	private DataDictionaryService dataDictionaryService;
	private KimTypeInfoService typeInfoService;
	
	protected final List<String> workflowRoutingAttributes = new ArrayList<String>();
	protected final List<String> requiredAttributes = new ArrayList<String>();
	protected boolean checkRequiredAttributes = false;

	@Override
	public String getWorkflowDocumentTypeName() {
		return null;
	}

	@Override
	public List<String> getWorkflowRoutingAttributes(String routeLevel) {
		return Collections.unmodifiableList(workflowRoutingAttributes);
	}

    @Override
	public AttributeDefinitionMap getAttributeDefinitions(String kimTypeId) {
        List<String> uniqueAttributes = getUniqueAttributes(kimTypeId);
        AttributeDefinitionMap definitions = new AttributeDefinitionMap();
        KimType kimType = getTypeInfoService().getKimType(kimTypeId);
        if ( kimType != null ) {
            String nsCode = kimType.getNamespaceCode();
            for (KimTypeAttribute typeAttribute : kimType.getAttributeDefinitions()) {
                AttributeDefinition definition = null;
                if (typeAttribute.getKimAttribute().getComponentName() == null) {
                    definition = getNonDataDictionaryAttributeDefinition(typeAttribute);
                } else {
                    definition = getDataDictionaryAttributeDefinition(nsCode,kimTypeId,typeAttribute);
                }

                if (definition != null) {
                    if(uniqueAttributes!=null && uniqueAttributes.contains(definition.getName())){
                        definition.setUnique(true);
                    }
                    definitions.put(typeAttribute.getSortCode(), definition);
                }
            }
        } else {
            LOG.warn( "Unable to resolve KIM Type: " + kimTypeId + " - returning an empty AttributeDefinitionMap." );
        }
		return definitions;
	}


    /**
	 * This is the default implementation.  It calls into the service for each attribute to
	 * validate it there.  No combination validation is done.  That should be done
	 * by overriding this method.
	 *
	 * @see org.kuali.rice.kim.api.type.KimTypeService#validateAttributes(Map<String, String>)
	 */
	@Override
	public Map<String, String> validateAttributes(String kimTypeId, Map<String, String> attributes) {
		Map<String,String> validationErrors = new HashMap<String, String>();
		if ( attributes == null ) {
			return Collections.emptyMap();
		}
		KimType kimType = getTypeInfoService().getKimType(kimTypeId);

		for ( Map.Entry<String, String> entry : attributes.entrySet() ) {
            KimTypeAttribute attr = kimType.getAttributeDefinitionByName(entry.getKey());
			final List<String> attributeErrors;
            if ( attr.getKimAttribute().getComponentName() == null) {
                attributeErrors = validateNonDataDictionaryAttribute(attr, entry.getKey(), entry.getValue());
            } else {
                attributeErrors = validateDataDictionaryAttribute(attr, entry.getKey(), entry.getValue());
            }

			if ( attributeErrors != null ) {
				for ( String err : attributeErrors ) {
					validationErrors.put(entry.getKey(), err);
				}
			}<commit_msg>minor change<commit_after>/*
 * Copyright 2007-2008 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 *
 * 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.kuali.rice.kim.impl.type;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.kuali.rice.core.api.util.ClassLoaderUtils;
import org.kuali.rice.core.api.util.RiceKeyConstants;
import org.kuali.rice.core.api.util.type.TypeUtils;
import org.kuali.rice.core.web.format.Formatter;
import org.kuali.rice.kew.doctype.bo.DocumentType;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;
import org.kuali.rice.kim.api.type.KimType;
import org.kuali.rice.kim.api.type.KimTypeAttribute;
import org.kuali.rice.kim.api.type.KimTypeInfoService;
import org.kuali.rice.kim.api.type.KimTypeService;
import org.kuali.rice.kim.bo.types.dto.AttributeDefinitionMap;
import org.kuali.rice.kns.lookup.LookupUtils;
import org.kuali.rice.kns.util.FieldUtils;
import org.kuali.rice.kns.web.ui.Field;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.comparator.StringValueComparator;
import org.kuali.rice.krad.datadictionary.AttributeDefinition;
import org.kuali.rice.krad.datadictionary.KimAttributeDefinition;
import org.kuali.rice.krad.datadictionary.KimDataDictionaryAttributeDefinition;
import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
import org.kuali.rice.krad.datadictionary.validation.ValidationPattern;
import org.kuali.rice.krad.keyvalues.KimAttributeValuesFinder;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DataDictionaryService;
import org.kuali.rice.krad.service.DictionaryValidationService;
import org.kuali.rice.krad.service.KRADServiceLocator;
import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
import org.kuali.rice.krad.util.ErrorMessage;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADUtils;
import org.kuali.rice.krad.util.ObjectUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

public class KimTypeServiceBase implements KimTypeService {

	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KimTypeServiceBase.class);

	private BusinessObjectService businessObjectService;
	private DictionaryValidationService dictionaryValidationService;
	private DataDictionaryService dataDictionaryService;
	private KimTypeInfoService typeInfoService;
	
	protected final List<String> workflowRoutingAttributes = new ArrayList<String>();
	protected final List<String> requiredAttributes = new ArrayList<String>();
	protected boolean checkRequiredAttributes = false;

	@Override
	public String getWorkflowDocumentTypeName() {
		return null;
	}

	@Override
	public List<String> getWorkflowRoutingAttributes(String routeLevel) {
		return Collections.unmodifiableList(workflowRoutingAttributes);
	}

    @Override
	public AttributeDefinitionMap getAttributeDefinitions(String kimTypeId) {
        List<String> uniqueAttributes = getUniqueAttributes(kimTypeId);
        AttributeDefinitionMap definitions = new AttributeDefinitionMap();
        KimType kimType = getTypeInfoService().getKimType(kimTypeId);
        if ( kimType != null ) {
            String nsCode = kimType.getNamespaceCode();
            for (KimTypeAttribute typeAttribute : kimType.getAttributeDefinitions()) {
                AttributeDefinition definition = null;
                if (typeAttribute.getKimAttribute().getComponentName() == null) {
                    definition = getNonDataDictionaryAttributeDefinition(typeAttribute);
                } else {
                    definition = getDataDictionaryAttributeDefinition(nsCode,kimTypeId,typeAttribute);
                }

                if (definition != null) {
                    if(uniqueAttributes!=null && uniqueAttributes.contains(definition.getName())){
                        definition.setUnique(true);
                    }
                    definitions.put(typeAttribute.getSortCode(), definition);
                }
            }
        } else {
            LOG.warn( "Unable to resolve KIM Type: " + kimTypeId + " - returning an empty AttributeDefinitionMap." );
        }
		return definitions;
	}


    /**
	 * This is the default implementation.  It calls into the service for each attribute to
	 * validate it there.  No combination validation is done.  That should be done
	 * by overriding this method.
	 */
	@Override
	public Map<String, String> validateAttributes(String kimTypeId, Map<String, String> attributes) {
		Map<String,String> validationErrors = new HashMap<String, String>();
		if ( attributes == null ) {
			return Collections.emptyMap();
		}
		KimType kimType = getTypeInfoService().getKimType(kimTypeId);

		for ( Map.Entry<String, String> entry : attributes.entrySet() ) {
            KimTypeAttribute attr = kimType.getAttributeDefinitionByName(entry.getKey());
			final List<String> attributeErrors;
            if ( attr.getKimAttribute().getComponentName() == null) {
                attributeErrors = validateNonDataDictionaryAttribute(attr, entry.getKey(), entry.getValue());
            } else {
                attributeErrors = validateDataDictionaryAttribute(attr, entry.getKey(), entry.getValue());
            }

			if ( attributeErrors != null ) {
				for ( String err : attributeErrors ) {
					validationErrors.put(entry.getKey(), err);
				}
			}
{'fraction_non_alphanumeric': 0.09642773756712585, 'fraction_numerical': 0.0020235037746128104, 'mean_word_length': 4.097183657278857, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2562797', 'n_tokens_mistral': 3727, 'n_tokens_neox': 3581, 'n_words': 758}