<commit_before>/*
 * Copyright 2006-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/ecl1.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.kra.award.service.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kuali.kra.award.bo.Award;
import org.kuali.kra.award.bo.AwardSyncable;
import org.kuali.kra.award.bo.AwardSyncableList;
import org.kuali.kra.award.bo.AwardTemplate;
import org.kuali.kra.award.bo.AwardTemplateComment;
import org.kuali.kra.award.service.AwardTemplateSyncService;
import org.kuali.rice.kns.service.BusinessObjectService;
import org.kuali.rice.kns.util.ObjectUtils;

/**
 * This class is the implementation of AwardTemplateSyncService.
 */
public class AwardTemplateSyncServiceImpl implements AwardTemplateSyncService {

    private BusinessObjectService businessObjectService;
    
    private static final Log LOG = LogFactory.getLog(AwardTemplateSyncServiceImpl.class);


    /**
     * This method is used to sync member properties of an award template object to an award object
     * 
     * @param awardTemplateObject
     * @param awardObject
     */
    private void sync(Object awardTemplateObject, Object awardObject) throws Exception{
        Field[] fields = awardObject.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (field.isAnnotationPresent(AwardSyncable.class)){
                copyField(awardTemplateObject, awardObject, field);
            }
            if(field.isAnnotationPresent(AwardSyncableList.class)){
                extractListFromParentAndSync(awardTemplateObject, awardObject, field);
            }
        }
    }

    /**
     * 
     * This method is to sync only fields; but not lists
     * @param awardTemplateObject
     * @param awardObject
     * @throws Exception
     */
    private void syncOnlyFields(Object awardTemplateObject, Object awardObject) throws Exception{
        Field[] fields = awardObject.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (field.isAnnotationPresent(AwardSyncable.class) &&
                    !field.getType().isAssignableFrom(List.class)){
                copyField(awardTemplateObject, awardObject, field);
            }
        }
    }
    /**
     * This method is for extracting the appropriate list from award by using property name and sync the list
     * @param awardTemplateObject
     * @param awardObject
     * @param propertyName
     * @param awardSyncableList 
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void extractListFromParentAndSync(Object awardTemplateObject, Object awardObject, Field field) throws Exception {
        List<Object> awardTemplateObjectList = (List)ObjectUtils.getPropertyValue(awardTemplateObject, field.getName());
        AwardSyncableList awardSyncableList = field.getAnnotation(AwardSyncableList.class);
        if(awardTemplateObjectList!=null && !awardTemplateObjectList.isEmpty()){
            if(awardSyncableList.syncMethodName().equalsIgnoreCase(AwardSyncableList.DEFAULT_METHOD)){
                syncListObjects(awardObject,awardTemplateObjectList,field);
            }else{
                invokeMethodToSync((Award)awardObject,awardTemplateObjectList,awardSyncableList.syncMethodName());
            }
        }
    }

    /**
     * 
     * This method is to invoke individual method if there is a method mentioned in the AwardSyncableList annotation
     * @param awardObject
     * @param awardTemplateObjectList
     * @param syncMethodName
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void invokeMethodToSync(Award awardObject, List awardTemplateObjectList,String syncMethodName) throws Exception{
        Method syncMethod = getClass().getMethod(syncMethodName, new Class[]{Award.class,List.class});
        syncMethod.invoke(this, new Object[]{awardObject,awardTemplateObjectList});
    }

    /**
     * 
     * This is an overloaded method to sync a particular list defined in Award object
     * @param awardTemplateObject
     * @param awardObject
     * @param propertyName
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void sync(Object awardTemplateObject, Object awardObject,String propertyName) throws Exception{
        List<Object> awardTemplateObjects = (List)ObjectUtils.getPropertyValue(awardTemplateObject, propertyName);
        Field field = awardObject.getClass().getField(propertyName);
        extractListFromParentAndSync(awardObject, awardTemplateObjects, field);
    }
    /**
     * This copies value from Award Template object to Award object
     * @param awardTemplateObject
     * @param awardObject
     * @param field
     * @throws Exception
     */
    private void copyField(Object awardTemplateObject, Object awardObject, Field field) throws Exception {
        if (field.isAnnotationPresent(AwardSyncable.class)){
            Object value = ObjectUtils.getPropertyValue(awardTemplateObject, field.getName());
            ObjectUtils.setObjectProperty(awardObject, field.getName(), value);
        }
    }
    /**
     * This is the default method use to sync objects. This method is implemented to work on row Object.
     * If we need to change the implementation of sync functionality for a specific list, 
     * we have to overload this method with specific type.
     * @param awardObject
     * @param listObject
     * @param objectInList
     * @param field
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void syncListObjects(Object awardObject, List<Object> listObject, Field field) 
                                                                                                throws Exception{
        AwardSyncableList awardSyncableList = field.getAnnotation(AwardSyncableList.class);
        String parentPropertyName = awardSyncableList.parentPropertyName();
        Class syncClass = awardSyncableList.syncClass();
        List<Object> newObjectList = new ArrayList<Object>(listObject.size());
        for (Object awardTemplateObject : listObject) {
            Object newObjectToSync = ObjectUtils.createNewObjectFromClass(syncClass);
            sync(awardTemplateObject, newObjectToSync);
            ObjectUtils.setObjectProperty(newObjectToSync, parentPropertyName, awardObject);
            newObjectList.add(newObjectToSync);
        }
        ObjectUtils.setObjectProperty(awardObject, field.getName(), newObjectList);
    }


    /**
     * This method is to fetch the award template by using template code from Award object.
     * 
     * @param Award object
     * @return AwardTemplate object
     */
    private AwardTemplate fetchAwardTemplate(Award award) {
        award.refreshReferenceObject("awardTemplate");
        AwardTemplate awardTemplate = award.getAwardTemplate();
        if (awardTemplate == null && award.getTemplateCode() != null) {
            Map<String, Integer> primaryKeys = new HashMap<String, Integer>();
            primaryKeys.put("templateCode", award.getTemplateCode());
            awardTemplate = (AwardTemplate) businessObjectService.findByPrimaryKey(AwardTemplate.class, primaryKeys);
        }
        return awardTemplate;
    }

    /**
     * Gets the businessObjectService attribute.
     * 
     * @return Returns the businessObjectService.
     */
    public BusinessObjectService getBusinessObjectService() {
        return businessObjectService;
    }

    /**
     * Sets the businessObjectService attribute value.
     * 
     * @param businessObjectService The businessObjectService to set.
     */
    public void setBusinessObjectService(BusinessObjectService businessObjectService) {<commit_msg>KCAWD-37 - Fixing award comments sync<commit_after>/*
 * Copyright 2006-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/ecl1.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.kra.award.service.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kuali.kra.award.bo.Award;
import org.kuali.kra.award.bo.AwardSyncable;
import org.kuali.kra.award.bo.AwardSyncableList;
import org.kuali.kra.award.bo.AwardTemplate;
import org.kuali.kra.award.bo.AwardTemplateComment;
import org.kuali.kra.award.service.AwardTemplateSyncService;
import org.kuali.rice.kns.service.BusinessObjectService;
import org.kuali.rice.kns.util.ObjectUtils;

/**
 * This class is the implementation of AwardTemplateSyncService.
 */
public class AwardTemplateSyncServiceImpl implements AwardTemplateSyncService {

    private BusinessObjectService businessObjectService;
    
    private static final Log LOG = LogFactory.getLog(AwardTemplateSyncServiceImpl.class);


    /**
     * This method is used to sync member properties of an award template object to an award object
     * 
     * @param awardTemplateObject
     * @param awardObject
     */
    private void sync(Object awardTemplateObject, Object awardObject) throws Exception{
        Field[] fields = awardObject.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (field.isAnnotationPresent(AwardSyncable.class)){
                copyField(awardTemplateObject, awardObject, field);
            }
            if(field.isAnnotationPresent(AwardSyncableList.class)){
                extractListFromParentAndSync(awardTemplateObject, awardObject, field);
            }
        }
    }

    /**
     * 
     * This method is to sync only fields; but not lists
     * @param awardTemplateObject
     * @param awardObject
     * @throws Exception
     */
    private void syncOnlyFields(Object awardTemplateObject, Object awardObject) throws Exception{
        Field[] fields = awardObject.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (field.isAnnotationPresent(AwardSyncable.class) &&
                    !field.getType().isAssignableFrom(List.class)){
                copyField(awardTemplateObject, awardObject, field);
            }
        }
    }
    /**
     * This method is for extracting the appropriate list from award by using property name and sync the list
     * @param awardTemplateObject
     * @param awardObject
     * @param propertyName
     * @param awardSyncableList 
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void extractListFromParentAndSync(Object awardTemplateObject, Object awardObject, Field field) throws Exception {
        List<Object> awardTemplateObjectList = (List)ObjectUtils.getPropertyValue(awardTemplateObject, field.getName());
        AwardSyncableList awardSyncableList = field.getAnnotation(AwardSyncableList.class);
        if(awardTemplateObjectList!=null && !awardTemplateObjectList.isEmpty()){
            if(awardSyncableList.syncMethodName().equalsIgnoreCase(AwardSyncableList.DEFAULT_METHOD)){
                syncListObjects(awardObject,awardTemplateObjectList,field);
            }else{
                invokeMethodToSync((Award)awardObject,awardTemplateObjectList,awardSyncableList.syncMethodName());
            }
        }
    }

    /**
     * 
     * This method is to invoke individual method if there is a method mentioned in the AwardSyncableList annotation
     * @param awardObject
     * @param awardTemplateObjectList
     * @param syncMethodName
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void invokeMethodToSync(Award awardObject, List awardTemplateObjectList,String syncMethodName) throws Exception{
        Method syncMethod = getClass().getMethod(syncMethodName, new Class[]{Award.class,List.class});
        syncMethod.invoke(this, new Object[]{awardObject,awardTemplateObjectList});
    }

    /**
     * 
     * This is an overloaded method to sync a particular list defined in Award object
     * @param awardTemplateObject
     * @param awardObject
     * @param propertyName
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void sync(Object awardTemplateObject, Object awardObject,String propertyName) throws Exception{
        Class awardtemplateClass =  awardTemplateObject.getClass();
        List<Object> awardTemplateObjects = new ArrayList();
        try{
            awardtemplateClass.getField(propertyName);
            awardTemplateObjects = (List)ObjectUtils.getPropertyValue(awardTemplateObject, propertyName);
        }catch(NoSuchFieldException nsfe){
            Method method = awardtemplateClass.getMethod("get"+propertyName, (Class[])null);
            awardTemplateObjects = (List) method.invoke(awardTemplateObject, (Object[])null);
        }
        Field field = awardObject.getClass().getField(propertyName);
        extractListFromParentAndSync(awardObject, awardTemplateObjects, field);
    }
    /**
     * This copies value from Award Template object to Award object
     * @param awardTemplateObject
     * @param awardObject
     * @param field
     * @throws Exception
     */
    private void copyField(Object awardTemplateObject, Object awardObject, Field field) throws Exception {
        if (field.isAnnotationPresent(AwardSyncable.class)){
            Object value = ObjectUtils.getPropertyValue(awardTemplateObject, field.getName());
            ObjectUtils.setObjectProperty(awardObject, field.getName(), value);
        }
    }
    /**
     * This is the default method use to sync objects. This method is implemented to work on row Object.
     * If we need to change the implementation of sync functionality for a specific list, 
     * we have to overload this method with specific type.
     * @param awardObject
     * @param listObject
     * @param objectInList
     * @param field
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void syncListObjects(Object awardObject, List<Object> listObject, Field field) 
                                                                                                throws Exception{
        AwardSyncableList awardSyncableList = field.getAnnotation(AwardSyncableList.class);
        String parentPropertyName = awardSyncableList.parentPropertyName();
        Class syncClass = awardSyncableList.syncClass();
        List<Object> newObjectList = new ArrayList<Object>(listObject.size());
        for (Object awardTemplateObject : listObject) {
            Object newObjectToSync = ObjectUtils.createNewObjectFromClass(syncClass);
            sync(awardTemplateObject, newObjectToSync);
            ObjectUtils.setObjectProperty(newObjectToSync, parentPropertyName, awardObject);
            newObjectList.add(newObjectToSync);
        }
        ObjectUtils.setObjectProperty(awardObject, field.getName(), newObjectList);
    }


    /**
     * This method is to fetch the award template by using template code from Award object.
     * 
     * @param Award object
     * @return AwardTemplate object
     */
    private AwardTemplate fetchAwardTemplate(Award award) {
        award.refreshReferenceObject("awardTemplate");
        AwardTemplate awardTemplate = award.getAwardTemplate();
        if (awardTemplate == null && award.getTemplateCode() != null) {
            Map<String, Integer> primaryKeys = new HashMap<String, Integer>();
            primaryKeys.put("templateCode", award.getTemplateCode());
            awardTemplate = (AwardTemplate) businessObjectService.findByPrimaryKey(AwardTemplate.class, primaryKeys);
            awardTemplate.getAwardComments();
        }
        return awardTemplate;
    }

    /**
     * Gets the businessObjectService attribute.
     * 
     * @return Returns the businessObjectService.
     */
    public BusinessObjectService getBusinessObjectService() {
        return businessObjectService;
    }

    /**
     * Sets the businessObjectService attribute value.
     * 
     * @param businessObjectService The businessObjectService to set.
     */
    public void setBusinessObjectService(BusinessObjectService businessObjectService) {
{'fraction_non_alphanumeric': 0.08320967926035841, 'fraction_numerical': 0.0015979910969067459, 'mean_word_length': 3.1425531914893616, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1796553', 'n_tokens_mistral': 4458, 'n_tokens_neox': 4407, 'n_words': 1173}