/* ===================================================================
 * ListManagerForm.java
 * 
 * Created Sep 7, 2005 7:25:20 AM
 * 
 * Copyright (c) 2005 Matt Magoffin (spamsqr@msqr.us)
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of 
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ===================================================================
 * $Id: ListManagerForm.java 62 2009-05-12 07:37:44Z msqr $
 * ===================================================================
 */

package magoffin.matt.ieat.web.setup;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import magoffin.matt.ieat.biz.DomainObjectFactory;
import magoffin.matt.ieat.biz.UserBiz;
import magoffin.matt.ieat.dao.BaseDao;
import magoffin.matt.ieat.dao.CourseDao;
import magoffin.matt.ieat.dao.DifficultyDao;
import magoffin.matt.ieat.dao.EthnicityDao;
import magoffin.matt.ieat.dao.IngredientDao;
import magoffin.matt.ieat.dao.PrepTimeDao;
import magoffin.matt.ieat.dao.RecipeDao;
import magoffin.matt.ieat.domain.Base;
import magoffin.matt.ieat.domain.Course;
import magoffin.matt.ieat.domain.Difficulty;
import magoffin.matt.ieat.domain.Ethnicity;
import magoffin.matt.ieat.domain.Ingredient;
import magoffin.matt.ieat.domain.PrepTime;
import magoffin.matt.ieat.web.WebUtil;
import magoffin.matt.xweb.XwebParameter;
import magoffin.matt.xweb.util.DynamicInitializer;
import magoffin.matt.xweb.util.DynamicInitializerRequestDataBinder;
import magoffin.matt.xweb.util.XwebParamDao;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

/**
 * Form controller for managing list data.
 * 
 * @author Matt Magoffin (spamsqr@msqr.us)
 * @version $Revision: 62 $ $Date: 2009-05-12 19:37:44 +1200 (Tue, 12 May 2009) $
 */
public class ListManagerForm extends SimpleFormController {
	
	/** The original value prefix. */
	public static final String ORIGINAL_VALUE_PREFIX = "_orig_";
	
	/** A key for deletion. */
	public static final String DELETE_KEY = "_delete_";
	
	/** Domain class. */
	public static class PropertyMetaData {
		
		private boolean primaryKey = false;
		
		private String name = null;
		
		private String displayName = null;
		
		/** Type of property: 1 = String, 2 = number, 3 = boolean */
		private int type = 1;
		
		private int length = 0;
		
		/**
		 * @return the displayName
		 */
		public String getDisplayName() {
			return displayName;
		}
		
		/**
		 * @param displayName the displayName to set
		 */
		public void setDisplayName(String displayName) {
			this.displayName = displayName;
		}
		
		/**
		 * @return the length
		 */
		public int getLength() {
			return length;
		}
		
		/**
		 * @param length the length to set
		 */
		public void setLength(int length) {
			this.length = length;
		}
		
		/**
		 * @return the name
		 */
		public String getName() {
			return name;
		}
		
		/**
		 * @param name the name to set
		 */
		public void setName(String name) {
			this.name = name;
		}
		
		/**
		 * @return the primaryKey
		 */
		public boolean isPrimaryKey() {
			return primaryKey;
		}
		
		/**
		 * @param primaryKey the primaryKey to set
		 */
		public void setPrimaryKey(boolean primaryKey) {
			this.primaryKey = primaryKey;
		}
		
		/**
		 * @return the type
		 */
		public int getType() {
			return type;
		}
		
		/**
		 * @param type the type to set
		 */
		public void setType(int type) {
			this.type = type;
		}
		
	}
	
	/** Metadata about our list of beans. */
	public static class ListMetaData {
		
		private PropertyMetaData[] properties;
		
		/**
		 * @return the properties
		 */
		public PropertyMetaData[] getProperties() {
			return properties;
		}
		
		/**
		 * @param properties the properties to set
		 */
		public void setProperties(PropertyMetaData[] properties) {
			this.properties = properties;
		}
		
	}
	
	/** The command object. */
	public static class ListCommand {
		private Class<?> beanClass = null;
		private Integer reassignPrimaryKey = null;
		private List<Map<String, Object>> beans = new ArrayList<Map<String,Object>>();
		private Map<String, Object> newBean = new LinkedHashMap<String, Object>();
		
		/**
		 * @return the beanClass
		 */
		public Class<?> getBeanClass() {
			return beanClass;
		}
		
		/**
		 * @param beanClass the beanClass to set
		 */
		public void setBeanClass(Class<?> beanClass) {
			this.beanClass = beanClass;
		}
		
		/**
		 * @return the beans
		 */
		public List<Map<String, Object>> getBeans() {
			return beans;
		}
		
		/**
		 * @param beans the beans to set
		 */
		public void setBeans(List<Map<String, Object>> beans) {
			this.beans = beans;
		}
		
		/**
		 * @return the newBean
		 */
		public Map<String, Object> getNewBean() {
			return newBean;
		}
		
		/**
		 * @param newBean the newBean to set
		 */
		public void setNewBean(Map<String, Object> newBean) {
			this.newBean = newBean;
		}
		
		/**
		 * @return the reassignPrimaryKey
		 */
		public Integer getReassignPrimaryKey() {
			return reassignPrimaryKey;
		}
		
		/**
		 * @param reassignPrimaryKey the reassignPrimaryKey to set
		 */
		public void setReassignPrimaryKey(Integer reassignPrimaryKey) {
			this.reassignPrimaryKey = reassignPrimaryKey;
		}
		
		
	}

	/** A dynamic initializer. */
	public static class ListInitializer implements DynamicInitializer {

		/* (non-Javadoc)
		 * @see magoffin.matt.ieat.util.DynamicInitializer#newInstance(java.lang.Object, java.lang.String)
		 */
		public Object newInstance(Object bean, String property) {
			return new LinkedHashMap<String, Object>();
		}
		
	}
	
	/** A validator. */
	public class ListValidator implements Validator {

		/* (non-Javadoc)
		 * @see org.springframework.validation.Validator#supports(java.lang.Class)
		 */
		@SuppressWarnings("unchecked")
		public boolean supports(Class clazz) {
			return ListCommand.class.isAssignableFrom(clazz);
		}

		/* (non-Javadoc)
		 * @see org.springframework.validation.Validator#validate(java.lang.Object, org.springframework.validation.Errors)
		 */
		public void validate(Object obj, Errors errors) {
			// verify that if any item marked for deletion, reassigned properly
			ListCommand listCmd = (ListCommand)obj;
			if ( listCmd.beans == null ) return;
			
			Set<Object> itemsToDelete = new LinkedHashSet<Object>();
			
			PropertyMetaData primaryKeyProp = getPrimaryKeyProperty(
					meta.get(listCmd.beanClass.getName()));
			
			for ( Iterator<Map<String, Object>> itr = listCmd.beans.iterator(); itr.hasNext(); ) {
				Map<String, Object> beanMap = itr.next();
				if ( beanMap.containsKey(DELETE_KEY) ) {
					itemsToDelete.add(beanMap.get(primaryKeyProp.name));
				}
			}
			
			if ( itemsToDelete.size() > 0 ) {
				if ( listCmd.reassignPrimaryKey == null ) {
					errors.reject("lists.reassign.required","Reassign item required.");
				} else if ( itemsToDelete.contains(listCmd.reassignPrimaryKey.toString()) ) {
					errors.reject("lists.reassign.illegal","Can't reassign to an item to delete.");
				}
			}
		}
		
	}
	
	private Map<String, ListMetaData> meta = null; // map of Class name to ListMetaData
	private RecipeDao recipeDao = null;
	private BaseDao baseDao = null;
	private CourseDao courseDao = null;
	private DifficultyDao difficultyDao = null;
	private EthnicityDao ethnicityDao = null;
	private IngredientDao ingredientDao = null;
	private PrepTimeDao prepTimeDao = null;
	private XwebParamDao parameterDao = null;
	private UserBiz userBiz = null;
	private DomainObjectFactory domainObjectFactory = null;
	
	private final Logger log = Logger.getLogger(getClass());
	
	private static final Pattern MSG_FORMAT = Pattern.compile("\\W");
	
	@Override
	protected void initApplicationContext() {
		setValidator(new ListValidator());
	}
	
	@Override
	protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object command)
    throws Exception {
		
		Map<String, DynamicInitializer> dynamicMap 
			= new LinkedHashMap<String, DynamicInitializer>();
		dynamicMap.put("beans",new ListInitializer());
		
		DynamicInitializerRequestDataBinder binder = 
			new DynamicInitializerRequestDataBinder(command,getCommandName(),
					dynamicMap);
		if (getMessageCodesResolver() != null) {
			binder.setMessageCodesResolver(getMessageCodesResolver());
		}
		initBinder(request, binder);
		return binder;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {
		WebUtil.getAdminBizContext(request,userBiz);
		ListCommand listCmd = (ListCommand)command;
		
		ListMetaData lmd = meta.get(listCmd.beanClass.getName());
		PropertyMetaData primaryKeyProp = getPrimaryKeyProperty(lmd);
		
		int updateCount = 0;
		
		// for any changed rows, update in DB
		for ( Iterator itr = listCmd.beans.iterator(); itr.hasNext(); ) {
			Map beanMap = (Map)itr.next();
			boolean changed = false;
			String pkValue = (String)beanMap.get(primaryKeyProp.name);
			
			if ( beanMap.containsKey(DELETE_KEY) ) {
				deleteBean(beanMap,request.getLocale(),listCmd.beanClass,
						pkValue,listCmd.reassignPrimaryKey);
				updateCount++;
				continue;
			}
			
			BeanWrapper bean = getBean(listCmd.beanClass,pkValue);
			
			for ( Iterator beanMapItr = beanMap.keySet().iterator(); beanMapItr.hasNext(); ) {
				String propName = (String)beanMapItr.next();
				if ( propName.startsWith("_") || propName.equals(primaryKeyProp.name)) {
					continue; // skip internal values and primary key
				}
				String propValue = (String)beanMap.get(propName);
				String propOrigValue = (String)beanMap.get(ORIGINAL_VALUE_PREFIX+propName);
				if ( !propValue.equals(propOrigValue) ) {
					changed = true;
					if ( log.isDebugEnabled() ) {
						log.debug("Changing property [" +propName +"] to ["
								+propValue +"] on bean [" 
								+listCmd.beanClass.getName() +"]");
					}
					bean.setPropertyValue(propName,propValue);
				}
			}
			if ( changed ) {
				saveBean(bean.getWrappedInstance(),beanMap,request.getLocale());
				updateCount++;
			}
		}
		
		// see if a new bean has been added
		boolean hasNew = false;
		BeanWrapper bean = getBean(listCmd.beanClass,null);
		for ( int i = 0; i < lmd.properties.length; i++ ) {
			PropertyMetaData pmd = lmd.properties[i];
			if ( pmd.primaryKey ) continue;
			String propValue = (String)listCmd.newBean.get(pmd.name);
			if ( StringUtils.hasText(propValue) ) {
				hasNew = true;
			}
			bean.setPropertyValue(pmd.name,propValue);
		}
		if ( hasNew ) {
			saveBean(bean.getWrappedInstance(),listCmd.newBean,request.getLocale());
			updateCount++;
		}
		
		Map<String, Object> model = errors.getModel();
		Map<String, Object> refData = referenceData(request,command,errors);
		model.putAll(refData);
		if ( updateCount > 0 ) {
			model.put("updateCount",new Integer(updateCount));
		}
		
		return new ModelAndView(getSuccessView(), model);
	}
	
	private void deleteBean(Map<String, Object> beanMap, Locale locale, Class<?> beanClass, 
			String pkValue, Integer reassignPrimaryKey) {
		Integer pk = Integer.valueOf(pkValue);
		String removeSettingKey = null;
		if ( Base.class.isAssignableFrom(beanClass) ) {
			recipeDao.reassignBase(pk,reassignPrimaryKey);
			baseDao.delete(baseDao.get(pk));
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				removeSettingKey = "msg:base." +locale.getLanguage() +":"
					+MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( Course.class.isAssignableFrom(beanClass) ) {
			recipeDao.reassignCourse(pk,reassignPrimaryKey);
			courseDao.delete(courseDao.get(pk));
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				removeSettingKey = "msg:course." +locale.getLanguage() +":"
					+MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( Difficulty.class.isAssignableFrom(beanClass) ) {
			recipeDao.reassignDifficulty(pk,reassignPrimaryKey);
			difficultyDao.delete(difficultyDao.get(pk));
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				removeSettingKey = "msg:difficulty." +locale.getLanguage() +":"
					+MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( Ethnicity.class.isAssignableFrom(beanClass) ) {
			recipeDao.reassignEthnicity(pk,reassignPrimaryKey);
			ethnicityDao.delete(ethnicityDao.get(pk));
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				removeSettingKey = "msg:ethnicity." +locale.getLanguage() +":"
					+MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( Ingredient.class.isAssignableFrom(beanClass) ) {
			recipeDao.reassignIngredient(pk,reassignPrimaryKey);
			ingredientDao.delete(ingredientDao.get(pk));
			String origValueKey = ORIGINAL_VALUE_PREFIX +"name";
			if ( beanMap.containsKey(origValueKey) ) {
				removeSettingKey = "msg:ingredient." +locale.getLanguage() +":"
					+MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( PrepTime.class.isAssignableFrom(beanClass) ) {
			recipeDao.reassignPrepTime(pk,reassignPrimaryKey);
			prepTimeDao.delete(prepTimeDao.get(pk));
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				removeSettingKey = "msg:course." +locale.getLanguage() +":"
					+MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		}

		if ( removeSettingKey != null ) {
			parameterDao.removeParameter(removeSettingKey);
		}
	}

	private void saveBean(Object bean, Map<String, Object> beanMap, Locale locale) {
		String settingKey = "msg:" +locale.getLanguage() +":";
		String origSettingKey = "msg:" +locale.getLanguage() +":";
		String settingValue = null;
		if ( bean instanceof Base ) {
			Base base = (Base)bean;
			baseDao.store(base);
			settingKey += "base." +MSG_FORMAT.matcher(base.getValue()).replaceAll("");
			settingValue = base.getValue();
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				origSettingKey += "base." +MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( bean instanceof Course ) {
			Course course = (Course)bean;
			courseDao.store(course);
			settingKey += "course." +MSG_FORMAT.matcher(course.getValue()).replaceAll("");
			settingValue = course.getValue();
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				origSettingKey += "course." +MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( bean instanceof Difficulty ) {
			Difficulty difficulty = (Difficulty)bean;
			difficultyDao.store(difficulty);
			settingKey += "difficulty." +MSG_FORMAT.matcher(difficulty.getValue()).replaceAll("");
			settingValue = difficulty.getValue();
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				origSettingKey += "difficulty." +MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( bean instanceof Ethnicity ) {
			Ethnicity ethnicity = (Ethnicity)bean;
			ethnicityDao.store(ethnicity);
			settingKey += "ethnicity." +MSG_FORMAT.matcher(ethnicity.getValue()).replaceAll("");
			settingValue = ethnicity.getValue();
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				origSettingKey += "ethnicity." +MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( bean instanceof Ingredient ) {
			Ingredient ingredient = (Ingredient)bean;
			ingredientDao.store(ingredient);
			settingKey += "ingredient." +MSG_FORMAT.matcher(ingredient.getName()).replaceAll("");
			settingValue = ingredient.getName();
			String origValueKey = ORIGINAL_VALUE_PREFIX +"name";
			if ( beanMap.containsKey(origValueKey) ) {
				origSettingKey += "ingredient." +MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		} else if ( bean instanceof PrepTime ) {
			PrepTime prepTime = (PrepTime)bean;
			prepTimeDao.store(prepTime);
			settingKey += "prepTime." +MSG_FORMAT.matcher(prepTime.getValue()).replaceAll("");
			settingValue = prepTime.getValue();
			String origValueKey = ORIGINAL_VALUE_PREFIX +"value";
			if ( beanMap.containsKey(origValueKey) ) {
				origSettingKey += "prepTime." +MSG_FORMAT.matcher(
						(String)beanMap.get(origValueKey)).replaceAll("");
			}
		}
		
		// remove old setting key (if changed)
		if ( !origSettingKey.equals(settingKey) ) {
			parameterDao.removeParameter(origSettingKey);
		}
		
		XwebParameter setting = this.domainObjectFactory.newXwebParameterInstance();
		setting.setKey(settingKey);
		setting.setValue(settingValue);
		parameterDao.updateParameter(setting);
	}

	private BeanWrapper getBean(Class<?> beanClass, String pkValue) {
		BeanWrapper result = null;
		if ( StringUtils.hasText(pkValue) ) {
			Integer pk = Integer.valueOf(pkValue);
			if ( Base.class.isAssignableFrom(beanClass) ) {
				result = new BeanWrapperImpl(baseDao.get(pk));
			} else if ( Course.class.isAssignableFrom(beanClass) ) {
				result = new BeanWrapperImpl(courseDao.get(pk));
			} else if ( Difficulty.class.isAssignableFrom(beanClass) ) {
				result = new BeanWrapperImpl(difficultyDao.get(pk));
			} else if ( Ethnicity.class.isAssignableFrom(beanClass) ) {
				result = new BeanWrapperImpl(ethnicityDao.get(pk));
			} else if ( Ingredient.class.isAssignableFrom(beanClass) ) {
				result = new BeanWrapperImpl(ingredientDao.get(pk));
			} else if ( PrepTime.class.isAssignableFrom(beanClass)) {
				result = new BeanWrapperImpl(prepTimeDao.get(pk));
			}
		} else {
			try {
				Object o = beanClass.newInstance();
				result = new BeanWrapperImpl(o);
			} catch (Exception e) {
				throw new RuntimeException("Unable to instantiate bean",e);
			}
		}
		return result;
	}

	private PropertyMetaData getPrimaryKeyProperty(ListMetaData lmd) {
		for ( int i = 0; i < lmd.properties.length; i++ ) {
			if ( lmd.properties[i].primaryKey ) {
				return lmd.properties[i];
			}
		}
		throw new IllegalArgumentException("No primary key found for ListMetaData");
	}

	@SuppressWarnings("unchecked")
	@Override
	protected Map referenceData(HttpServletRequest request, Object command,
			Errors errors) throws Exception {
		WebUtil.getAdminBizContext(request,userBiz);

		ListCommand listCmd = (ListCommand)command;

		// pull data from backend DB
		if ( listCmd.beanClass == null ) {
			return null;
		}
		
		List beanList = Collections.EMPTY_LIST;
		if ( Base.class.isAssignableFrom(listCmd.beanClass) ) {
			beanList = baseDao.getBases();
		} else if ( Course.class.isAssignableFrom(listCmd.beanClass) ) {
			beanList = courseDao.getCourses();
		} else if ( Difficulty.class.isAssignableFrom(listCmd.beanClass) ) {
			beanList = difficultyDao.getDifficulties();
		} else if ( Ethnicity.class.isAssignableFrom(listCmd.beanClass) ) {
			beanList = ethnicityDao.getEthnicities();
		} else if ( Ingredient.class.isAssignableFrom(listCmd.beanClass) ) {
			beanList = ingredientDao.getIngredients();
		} else if ( PrepTime.class.isAssignableFrom(listCmd.beanClass) ) {
			beanList = prepTimeDao.getPrepTimes();
		}
		
		listCmd.beans = new ArrayList<Map<String,Object>>(beanList.size()*2);
		for ( Iterator itr = beanList.iterator(); itr.hasNext(); ) {
			Object bean = itr.next();
			BeanWrapper wrapper = new BeanWrapperImpl(bean);
			Map<String, Object> beanMap = new LinkedHashMap<String, Object>();
			listCmd.beans.add(beanMap);
			ListMetaData lmd = this.meta.get(listCmd.beanClass.getName());
			for ( int j = 0; j < lmd.properties.length; j++ ) {
				Object value = wrapper.getPropertyValue(lmd.properties[j].name);
				value = value == null ? "" : value.toString();
				String name = lmd.properties[j].name;
				beanMap.put(name,value);
				beanMap.put(ORIGINAL_VALUE_PREFIX+name,value);
			}
		}

		Map<String, Object> data = new LinkedHashMap<String, Object>();
		data.put("meta",this.meta);
		return data;
	}
	
	/**
	 * @return the baseDao
	 */
	public BaseDao getBaseDao() {
		return baseDao;
	}

	/**
	 * @param baseDao the baseDao to set
	 */
	public void setBaseDao(BaseDao baseDao) {
		this.baseDao = baseDao;
	}
	
	/**
	 * @return the courseDao
	 */
	public CourseDao getCourseDao() {
		return courseDao;
	}
	
	/**
	 * @param courseDao the courseDao to set
	 */
	public void setCourseDao(CourseDao courseDao) {
		this.courseDao = courseDao;
	}
	
	/**
	 * @return the difficultyDao
	 */
	public DifficultyDao getDifficultyDao() {
		return difficultyDao;
	}
	
	/**
	 * @param difficultyDao the difficultyDao to set
	 */
	public void setDifficultyDao(DifficultyDao difficultyDao) {
		this.difficultyDao = difficultyDao;
	}
	
	/**
	 * @return the domainObjectFactory
	 */
	public DomainObjectFactory getDomainObjectFactory() {
		return domainObjectFactory;
	}
	
	/**
	 * @param domainObjectFactory the domainObjectFactory to set
	 */
	public void setDomainObjectFactory(DomainObjectFactory domainObjectFactory) {
		this.domainObjectFactory = domainObjectFactory;
	}
	
	/**
	 * @return the ethnicityDao
	 */
	public EthnicityDao getEthnicityDao() {
		return ethnicityDao;
	}
	
	/**
	 * @param ethnicityDao the ethnicityDao to set
	 */
	public void setEthnicityDao(EthnicityDao ethnicityDao) {
		this.ethnicityDao = ethnicityDao;
	}
	
	/**
	 * @return the ingredientDao
	 */
	public IngredientDao getIngredientDao() {
		return ingredientDao;
	}
	
	/**
	 * @param ingredientDao the ingredientDao to set
	 */
	public void setIngredientDao(IngredientDao ingredientDao) {
		this.ingredientDao = ingredientDao;
	}
	
	/**
	 * @return the meta
	 */
	public Map<String, ListMetaData> getMeta() {
		return meta;
	}
	
	/**
	 * @param meta the meta to set
	 */
	public void setMeta(Map<String, ListMetaData> meta) {
		this.meta = meta;
	}
	
	/**
	 * @return the prepTimeDao
	 */
	public PrepTimeDao getPrepTimeDao() {
		return prepTimeDao;
	}
	
	/**
	 * @param prepTimeDao the prepTimeDao to set
	 */
	public void setPrepTimeDao(PrepTimeDao prepTimeDao) {
		this.prepTimeDao = prepTimeDao;
	}
	
	/**
	 * @return the recipeDao
	 */
	public RecipeDao getRecipeDao() {
		return recipeDao;
	}
	
	/**
	 * @param recipeDao the recipeDao to set
	 */
	public void setRecipeDao(RecipeDao recipeDao) {
		this.recipeDao = recipeDao;
	}
	
	/**
	 * @return the userBiz
	 */
	public UserBiz getUserBiz() {
		return userBiz;
	}
	
	/**
	 * @param userBiz the userBiz to set
	 */
	public void setUserBiz(UserBiz userBiz) {
		this.userBiz = userBiz;
	}
	
	/**
	 * @return the parameterDao
	 */
	public XwebParamDao getParameterDao() {
		return parameterDao;
	}
	
	/**
	 * @param parameterDao the parameterDao to set
	 */
	public void setParameterDao(XwebParamDao parameterDao) {
		this.parameterDao = parameterDao;
	}

}
