package com.k_int.ciim.kernel;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MultivaluedMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.k_int.aggr2.mimsy.data.hdo.CIIMGroupContextHDO;
import com.k_int.aggr2.mimsy.data.hdo.CIIMGroupHDO;
import com.k_int.aggr2.mimsy.data.hdo.CIIMImgResizeFormatHDO;
import com.k_int.aggr2.mimsy.data.hdo.CIIMMediaDescriptionHDO;
import com.k_int.aggr2.mimsy.data.hdo.ElementDefinitionHDO;
import com.k_int.aggr2.mimsy.data.hdo.GroupHierarchyXRTreeHDO;
import com.k_int.aggr2.mimsy.data.hdo.MimsyCuratedGroupHDO;
import com.k_int.aggr2.mimsy.data.hdo.SchemaDefinitionHDO;
import com.k_int.aggr2.mimsy.data.hdo.SchemaElementHDO;
import com.k_int.aggr2.mimsy.data.hdo.SchemaOptionValueHDO;
import com.k_int.ciim.json.CIIMBaseMimsyJSON;
import com.k_int.ciim.json.CIIMGroupAttachmentJSON;
import com.k_int.ciim.json.CIIMGroupJSON;
import com.k_int.ciim.json.CIIMMediaFormatJSON;
import com.k_int.ciim.json.CIIMObjectJSON;
import com.k_int.ciim.json.SchemaDefinitionJSON;
import com.k_int.ciim.json.ValidationResultJSON;
import com.k_int.ciim.ref.Constants;
import com.k_int.ciim.utils.IdentityServiceWrapper;
import com.k_int.mimsy.ref.DataStatusEnum;
import com.k_int.mimsy.ref.ElementDefinitionTypeEnum;
import com.k_int.mimsy.ref.GroupPublicationStatusEnum;
import com.k_int.mimsy.ref.MediaRecordTypeEnum;
import com.k_int.mimsy.ref.MimsyDataTypeEnum;
import com.k_int.mimsy.ref.SchemaElementTypeEnum;
import com.k_int.svc.identity.service.IdentityService;
import com.k_int.svc.identity.service.IdentityServiceException;

public class CIIMDataManager implements ApplicationContextAware
{
	private static Log log = LogFactory.getLog(GroupQueryCore.class);

	//Beans
	private ApplicationContext ctx;
	private SessionFactory factory = null;
	private GroupQueryCore gqc;
	private GroupTransactionCore gtc;
	private ValidationQueryCore vqc;
	private MimsyDataTransactionCore mtc;
	private MimsyDataQueryCore mqc;
	private HierarchyQueryCore hqc;
	private HierarchyTransactionCore htc;
	private AttachmentQueryCore aqc;
	private AttachmentTransactionCore atc;
	private SchemaQueryCore sqc;
		  
	public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.ctx = ctx; }
	
	public void setSessionFactory(SessionFactory factory) {	this.factory = factory; }
	
	public void setGroupQueryCore(GroupQueryCore gqc) {	this.gqc = gqc;	}
	
	public void setGroupTransactionCore(GroupTransactionCore gtc){ this.gtc = gtc; }
	
	public void setValidationQueryCore(ValidationQueryCore vqc) { this.vqc = vqc; }
	
	public void setMimsyDataTransactionCore(MimsyDataTransactionCore mtc) { this.mtc = mtc; }
	
	public void setMimsyDataQueryCore(MimsyDataQueryCore mqc) { this.mqc = mqc; }
	
	public void setHierarchyQueryCore(HierarchyQueryCore hqc) { this.hqc = hqc; }
	
	public void setHierarchyTransactionCore(HierarchyTransactionCore htc) { this.htc = htc; }
	
	public void setAttachmentQueryCore(AttachmentQueryCore aqc) { this.aqc = aqc; }
	
	public void setAttachmentTransactionCore(AttachmentTransactionCore atc) { this.atc = atc; }
	
	public void setSchemaQueryCore(SchemaQueryCore sqc) { this.sqc = sqc; }	
	
	@javax.annotation.PostConstruct
	public void init() 
	{
		Session session = null;
		
		try 
		{
			session = SessionFactoryUtils.getSession(factory, true);
			
			
			//CREATE DEFAULT GROUP SCHEMA
			SchemaDefinitionHDO test = SchemaDefinitionHDO.lookupByTitle(session, "GROUP DEFAULT");
			if(test==null)
			{
				Transaction tx = session.beginTransaction();
				
				SchemaDefinitionHDO default_group_schema = SchemaDefinitionHDO.lookupOrCreate(session, "GROUP DEFAULT");	
				default_group_schema.setDescription("The default schema for groups");	
				default_group_schema.setApplicableMimsyDataType(MimsyDataTypeEnum.GROUP);
				
				SchemaDefinitionHDO default_object_schema = SchemaDefinitionHDO.lookupOrCreate(session, "OBJECT DEFAULT");	
				default_object_schema.setDescription("The default schema for objects");	
				default_object_schema.setApplicableMimsyDataType(MimsyDataTypeEnum.OBJECT);
				
				//CREATE ELEMENT DEFINITIONS
				
				List<MimsyDataTypeEnum> obj_only = new ArrayList<MimsyDataTypeEnum>();
				obj_only.add(MimsyDataTypeEnum.OBJECT);
				List<MimsyDataTypeEnum> obj_and_group = new ArrayList<MimsyDataTypeEnum>();
				obj_and_group.add(MimsyDataTypeEnum.OBJECT);
				obj_and_group.add(MimsyDataTypeEnum.GROUP);
					
				ElementDefinitionHDO definition1 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOption1");	
				definition1.setApplicableMimsyDataTypes(obj_and_group);
				session.update(definition1);
				
				ElementDefinitionHDO definition2 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOption2");
				definition2.setApplicableMimsyDataTypes(obj_and_group);
				session.update(definition2);
				
				ElementDefinitionHDO definition3 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOption3");
				definition3.setApplicableMimsyDataTypes(obj_and_group);
				session.update(definition3);
				
				ElementDefinitionHDO definition4 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOption4");
				definition4.setApplicableMimsyDataTypes(obj_and_group);
				session.update(definition4);
				
				ElementDefinitionHDO definition5 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOption5");
				definition5.setApplicableMimsyDataTypes(obj_and_group);
				session.update(definition5);
				
				ElementDefinitionHDO definition6 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOption6");
				definition6.setApplicableMimsyDataTypes(obj_only);
				session.update(definition6);
				
				ElementDefinitionHDO definition7 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOtherNumber");
				definition7.setApplicableMimsyDataTypes(obj_only);
				definition7.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition7);
				
				ElementDefinitionHDO definition8 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOtherName");
				definition8.setApplicableMimsyDataTypes(obj_only);
				definition8.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition8);
				
				ElementDefinitionHDO definition9 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOtherTitle");
				definition9.setApplicableMimsyDataTypes(obj_only);
				definition9.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition9);
				
				ElementDefinitionHDO definition10 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOtherDescription");
				definition10.setApplicableMimsyDataTypes(obj_only);
				definition10.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition10);
				
				ElementDefinitionHDO definition11 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOtherDescriptionDate");
				definition11.setApplicableMimsyDataTypes(obj_only);
				definition11.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition11);
				
				ElementDefinitionHDO definition12 = ElementDefinitionHDO.lookupOrCreate(session, "extensionOtherDescriptionAuthor");
				definition12.setApplicableMimsyDataTypes(obj_only);
				definition12.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition12);
				
				ElementDefinitionHDO definition13 = ElementDefinitionHDO.lookupOrCreate(session, "extensionUpdatedBy");
				definition13.setApplicableMimsyDataTypes(obj_only);
				definition13.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition13);
				
				ElementDefinitionHDO definition14 = ElementDefinitionHDO.lookupOrCreate(session, "extensionUpdateDate");
				definition14.setApplicableMimsyDataTypes(obj_only);
				definition14.setDefinitionType(ElementDefinitionTypeEnum.FIXED);
				session.update(definition14);
				
				//CREATE SCHEMA ELEMENTS
				
				/* GROUP */
				SchemaElementHDO group_element1 = SchemaElementHDO.lookupOrCreate(session, null, definition1);
				group_element1.setDisplayName("Option 1");
				group_element1.setSchemaElementType(SchemaElementTypeEnum.NUMERIC);
				group_element1.setMaxLength(10);
				session.update(group_element1);
				
				SchemaElementHDO group_element2 = SchemaElementHDO.lookupOrCreate(session, null, definition2);
				group_element2.setDisplayName("Option 2");
				group_element2.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				group_element2.setMaxLength(500);
				session.update(group_element2);
				
				SchemaElementHDO group_element3 = SchemaElementHDO.lookupOrCreate(session, null, definition3);
				group_element3.setDisplayName("Option 3");
				group_element3.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				group_element3.setMaxLength(4000);
				session.update(group_element3);
				
				SchemaElementHDO group_element4 = SchemaElementHDO.lookupOrCreate(session, null, definition4);
				group_element4.setDisplayName("Option 4");
				group_element4.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				group_element4.setMaxLength(4000);
				session.update(group_element4);
				
				SchemaElementHDO group_element5 = SchemaElementHDO.lookupOrCreate(session, null, definition5);
				group_element5.setDisplayName("Option 5");
				group_element5.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				group_element5.setMaxLength(4000);
				session.update(group_element5);
				
				/* OBJECT */
				
				SchemaElementHDO object_element1 = SchemaElementHDO.lookupOrCreate(session, null, definition1);
				object_element1.setDisplayName("Option 1");
				object_element1.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				object_element1.setMaxLength(4000);
				session.update(object_element1);
				
				SchemaElementHDO object_element2 = SchemaElementHDO.lookupOrCreate(session, null, definition2);
				object_element2.setDisplayName("Option 2");
				object_element2.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				object_element2.setMaxLength(4000);
				session.update(object_element2);
				
				SchemaElementHDO object_element3 = SchemaElementHDO.lookupOrCreate(session, null, definition3);
				object_element3.setDisplayName("Option 3");
				object_element3.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				object_element3.setMaxLength(4000);
				session.update(object_element3);
				
				SchemaElementHDO object_element4 = SchemaElementHDO.lookupOrCreate(session, null, definition4);
				object_element4.setDisplayName("Option 4");
				object_element4.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element4.setMaxLength(500);
				session.update(object_element4);
				
				SchemaElementHDO object_element5 = SchemaElementHDO.lookupOrCreate(session, null, definition5);
				object_element5.setDisplayName("Option 5");
				object_element5.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element5.setMaxLength(500);
				session.update(object_element5);
				
				SchemaElementHDO object_element6 = SchemaElementHDO.lookupOrCreate(session, null, definition6);
				object_element6.setDisplayName("Option 6");
				object_element6.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element6.setMaxLength(500);
				session.update(object_element6);
				
				SchemaElementHDO object_element7 = SchemaElementHDO.lookupOrCreate(session, null, definition7);
				object_element7.setDisplayName("Other Number");
				object_element7.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element7.setMaxLength(50);
				session.update(object_element7);
				
				SchemaElementHDO object_element8 = SchemaElementHDO.lookupOrCreate(session, null, definition8);
				object_element8.setDisplayName("Other Name");
				object_element8.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element8.setMaxLength(500);
				session.update(object_element8);
				
				SchemaElementHDO object_element9 = SchemaElementHDO.lookupOrCreate(session, null, definition9);
				object_element9.setDisplayName("Other Title");
				object_element9.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element9.setMaxLength(500);
				session.update(object_element9);
				
				SchemaElementHDO object_element10 = SchemaElementHDO.lookupOrCreate(session, null, definition10);
				object_element10.setDisplayName("Other Description");
				object_element10.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				object_element10.setMaxLength(4000);
				session.update(object_element10);
				
				SchemaElementHDO object_element11 = SchemaElementHDO.lookupOrCreate(session, null, definition11);
				object_element11.setDisplayName("Other Description Date");
				object_element11.setSchemaElementType(SchemaElementTypeEnum.DATE);
				object_element11.setMaxLength(10);
				session.update(object_element11);
				
				SchemaElementHDO object_element12 = SchemaElementHDO.lookupOrCreate(session, null, definition12);
				object_element12.setDisplayName("Other Description Author");
				object_element12.setSchemaElementType(SchemaElementTypeEnum.WYSIWYG);
				object_element12.setMaxLength(50);
				session.update(object_element12);
				
				SchemaElementHDO object_element13 = SchemaElementHDO.lookupOrCreate(session, null, definition13);
				object_element13.setDisplayName("Updated by");
				object_element13.setSchemaElementType(SchemaElementTypeEnum.TEXT);
				object_element13.setMaxLength(50);
				session.update(object_element13);
				
				SchemaElementHDO object_element14 = SchemaElementHDO.lookupOrCreate(session, null, definition14);
				object_element14.setDisplayName("Update Date");
				object_element14.setSchemaElementType(SchemaElementTypeEnum.DATE);
				object_element14.setMaxLength(10);
				session.update(object_element14);
					
				//ADD ELEMENTS TO DEFAULT SCHEMA DEFINITION	
				List<SchemaElementHDO> group_schema_elements = default_group_schema.getSchemaElements();
				
				group_schema_elements.clear();
				
				group_schema_elements.add(group_element1);
				group_schema_elements.add(group_element2);
				group_schema_elements.add(group_element3);
				group_schema_elements.add(group_element4);
				group_schema_elements.add(group_element5);
				
				default_group_schema.setSchemaElements(group_schema_elements);
				session.saveOrUpdate(default_group_schema);
				
				List<SchemaElementHDO> object_schema_elements = default_object_schema.getSchemaElements();
				
				object_schema_elements.clear();
				
				object_schema_elements.add(object_element1);
				object_schema_elements.add(object_element2);
				object_schema_elements.add(object_element3);
				object_schema_elements.add(object_element4);
				object_schema_elements.add(object_element5);
				object_schema_elements.add(object_element6);
				object_schema_elements.add(object_element7);
				object_schema_elements.add(object_element8);
				object_schema_elements.add(object_element9);
				object_schema_elements.add(object_element10);
				object_schema_elements.add(object_element11);
				object_schema_elements.add(object_element12);
				object_schema_elements.add(object_element13);
				object_schema_elements.add(object_element14);
				
				default_object_schema.setSchemaElements(object_schema_elements);	
				session.saveOrUpdate(default_object_schema);
				
				session.flush();
				tx.commit();	
			}
			
		}
		catch (HibernateException he) 
		{
			log.error("[firstrun:1] Error initialising default group schema definition", he);
		} 
		catch (Exception e) 
		{
			log.error("[firstrun:1] Error initialising default group schema definition", e);
		} 
 	}
	
	/**
	 *  Group Functions 
	 */

		/* Return a specific group as JSON object */
	
		private CIIMGroupJSON getCIIMGroupJSON(Session session, CIIMGroupHDO hdo, HttpServletRequest request)
		{
			CIIMGroupJSON retval = convertHDOtoJSON(session, hdo, request);
			  
			if(retval != null)
			{
				// Get a list of the top groups
				List<String> top_group_ids = hqc.getTopGroupIds(session);
				  
				// If there are no top groups there can be no relationships
				if(top_group_ids != null &&  top_group_ids.size() > 0)
				{
					//If the object returned is a top group we only need to get the children in context to itself
					if(top_group_ids.contains(retval.gid))
					{
						retval.hier = CIIMGroupJSON.HIERARCHY_TOP;
						  
						//As we are the top group we dont need to check the other top groups
						ArrayList<String> lSelf = new ArrayList<String>();
						lSelf.add(retval.gid);
						  
						this.assignHierarchyDataToGroup(session, lSelf, retval);
					}
					else
					{
						//Initialise to no hierarchy
						retval.hier = CIIMGroupJSON.HIERARCHY_NONE;
						  
						this.assignHierarchyDataToGroup(session, top_group_ids, retval);
					}
				}
				
				retval.setAttachments(aqc.getAttachments(session, hdo.getCuratedGroup().getId().toString()));
				
				//Get number of items 
			    Long items_no = mqc.getGroupItemCount(session, hdo.getCuratedGroup().getId());
			    
			    if(items_no != null)
			    {
			    	//set value to json object
			    	retval.items = items_no.toString();
			    }
			}		 
				  
			return retval;  
		}

		/* QUERY : Returns a list of all Groups as JSON */
		
		public List<CIIMGroupJSON> getGroups(HttpServletRequest request) 
		{
			List<CIIMGroupJSON> retval = new ArrayList<CIIMGroupJSON>();		
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				List<CIIMGroupHDO> groups = gqc.getGroups(session);
				
				// Iterate through the objects returned from the query
	    		for(CIIMGroupHDO hdo : groups)
	    		{
	    			// And convert to JSON objects
	    			CIIMGroupJSON json = getCIIMGroupJSON(session, hdo, request);
		    	  
	    			// if Object is not null so then we need to see if there are relationships to be added
	    			if(json != null)
	    			{	  	    		   				
	    				retval.add(json);
	    			}
	    		}
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in cascade publication method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with cascade publication method", e);
			} 
			
			return retval;
				
		}
		
		/* TRANSACTION : Update a Group and return the updated object as JSON */
		
		public void updateCIIMGroup(MultivaluedMap<String, String> form_params, 
									HttpServletRequest request)
		{
			String gid = form_params.getFirst("gid");
			
			if(this.userHasPermissions(request, gid))
			{
				Session session = null;
				
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					gtc.updateCIIMGroup(session, form_params);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in cascade publication method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with cascade publication method", e);
				} 
			}
		}
	
		/* QUERY : returns the publication status of a specific group */
	
		public GroupPublicationStatusEnum getPublicationStatus(String gid)
		{
			GroupPublicationStatusEnum retval = null;

			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = gqc.getPublicationStatus(session, gid);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in cascade publication method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with cascade publication method", e);
			} 
			return retval;
				
		}
			
		/* QUERY : check to see if group is a top group */
		
		public boolean isTopGroup(String gid)
		{
			boolean retval = false;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = gqc.isTopGroup(session, gid);	
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in cascade publication method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with cascade publication method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : informs whether a group is ready or not to be published */
		
		public boolean readyToPublish(String gid)
		{
			boolean retval = false;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = gqc.readyToPublish(session, gid);	
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in cascade publication method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with cascade publication method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : returns all top groups related to the input group */
		
		public List<String> getAssociatedTopGroups(String gid)
		{
			List<String> retval = null;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = hqc.getAssociatedTopGroups(session, gid);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getAssociatedTopGroups method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getAssociatedTopGroups method", e);
			} 
			
			
			return retval;
		}
		
		/* TRANSACTION : Cascades a specific publication status through to all related groups in a hierarchy */
	
		public void cascadePublicationStatus(String top_group_id, GroupPublicationStatusEnum status, HttpServletRequest request)
		{
			if(this.userHasPermissions(request, top_group_id))
			{
				Session session = null;
				  
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					gtc.cascadePublicationStatus(session, top_group_id, status);			
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in cascade publication method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with cascade publication method", e);
				} 
			}
		}
	
	/**
	 *  Hierarchy Functions 
	 */
		
		/* Assign hierarchy data to a Group */
		
		private void assignHierarchyDataToGroup(Session session, List<String> top_group_list, CIIMGroupJSON group)
		{	
			if(group != null && top_group_list != null && top_group_list.size() > 0)
			{
				// Iterate through all top groups to find all related children of this object
				for(String top_group_id : top_group_list)
				{
					// To do this we first need to find its position in the 'tree'. 
					// Tree id will be null if it has no children in the context of the current top group in iteration
					GroupHierarchyXRTreeHDO hierarchy_hdo = hqc.getGroupHierarchyData(session, group.gid, top_group_id);
					  
					if(hierarchy_hdo != null && hierarchy_hdo.getCurrent())
					{
						// We now know at minimum this is a leaf so ensure that its hierarchy is upgraded.
						if(group.hier == CIIMGroupJSON.HIERARCHY_NONE)
						{
							group.hier = CIIMGroupJSON.HIERARCHY_NODE;
						}
						  
						//first populate position
						if(hierarchy_hdo.getPosition() != null)
						{
							group.addPosition(top_group_id, hierarchy_hdo.getPosition());
						}  
						//then populate relationships
						if(hierarchy_hdo.getTree_id() != null && hierarchy_hdo.getTree_id().length() > 0)
						{					  
							List<String> children = hqc.getChildrenGroupIds(session, hierarchy_hdo.getTree_id());
							  
							if(children != null && children.size() > 0)
							{						  
								for(String child_id : children)
								{
									//If this is a legitimate relationship it will be added and the hierarchy will be upgraded to NODE
									group.addRelationship(top_group_id, child_id);
								}
							}
						}
					}	    		
				}
			}
		}
		
		/* TRANSACTION : inserts a group into a existing hierarchy structure */
		
		public synchronized boolean insertIntoTree(String gid, String node_id, String top_group_id, HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null;
			 
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && this.userHasPermissions(request, gid) && this.userHasPermissions(request, top_group_id)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = htc.insertIntoTree(session, gid, node_id, top_group_id);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in insertIntoTree method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with insertIntoTree method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION : removes a group from a hierarchy structure */
		
		public synchronized boolean removeFromTree(String gid, String top_group_id, HttpServletRequest request)
		{ 	
			boolean retval = false;
			Session session = null;
			  
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && this.userHasPermissions(request, gid) && this.userHasPermissions(request, top_group_id)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = htc.removeFromTree(session, gid, top_group_id);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in removeFromTree method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with removeFromTree method", e);
				} 
			}
		
			return retval;
		}
		
		/* TRANSACTION : promotes a group inside a specific node level of an existing hierarchy structure */
		
		public boolean promoteGroupPosition(String gid, String node_id, String top_group_id, Boolean promote, HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null;
			  
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && this.userHasPermissions(request, gid) && this.userHasPermissions(request, top_group_id)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = htc.promoteGroupPosition(session, gid, node_id, top_group_id, promote);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in removeFromTree method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with removeFromTree method", e);
				} 
			}
		
			return retval;
		}
		
		/* TRANSACTION : sets a group as a top group from which a hierarchy can be built */
		
		public void setAsTopGroup(String gid, HttpServletRequest request)
		{
			Session session = null;
			
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					htc.setAsTopGroup(session, gid);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in setAsTopGroup method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1] Problem with setAsTopGroup method", e);
				} 
			}
		}
		
		/* TRANSACTION : removes a group from the top group position if it has no children */
		
		public void removeAsTopGroup(String gid, HttpServletRequest request)
		{
			Session session = null;
			
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					htc.removeAsTopGroup(session, gid);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in removeAsTopGroup method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1] Problem with removeAsTopGroup method", e);
				} 
			}
		}
	 

	/**
	 *  Attachment Functions 
	 */
	
		/* TRANSACTION : creates a new CIIM Media Description object */
		public boolean createCIIMMediaDescription(String name, String location, MediaRecordTypeEnum type, HttpServletRequest request, Long height, Long width)
		{
			boolean retval = false;
			Session session = null;
			  
			if(request != null && (request.isUserInRole(Constants.CIIM_EDITOR_ROLE) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = atc.createCIIMMediaDescription(session, name, location, type, height, width);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in removeAsTopGroup method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1] Problem with removeAsTopGroup method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION : adds a specific attachment to a group */
		public void addAttachment(Long id, String gid, HttpServletRequest request)
		{
			Session session = null;
			
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					atc.addAttachment(session, id, gid);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with transaction in addAttachment method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1] Problem with addAttachment method", e);
				} 
			}
		}
		
		/* QUERY : Returns all attachments */
		
		public List<CIIMGroupAttachmentJSON> getAllAttachments()
		{	
			List<CIIMGroupAttachmentJSON> retval = new ArrayList<CIIMGroupAttachmentJSON>();
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getAllAttachments(session);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getAllAttachments method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getAllAttachments method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : returns all attachments assigned to a specific group */
		
		public List<CIIMGroupAttachmentJSON> getAttachments(String gid)
		{
			List<CIIMGroupAttachmentJSON> retval = new ArrayList<CIIMGroupAttachmentJSON>();
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getAttachments(session, gid);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getAttachments method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getAttachments method", e);
			} 
			
			return retval;		  
		}
		
		/* QUERY : returns all attachments NOT assigned to a specific group */
		
		public List<CIIMGroupAttachmentJSON> getUnassignedAttachments(String gid)
		{
			List<CIIMGroupAttachmentJSON> retval = new ArrayList<CIIMGroupAttachmentJSON>();
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getUnassignedAttachments(session, gid);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getUnassignedAttachments method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getUnassignedAttachments method", e);
			} 
			
			return retval;		  
		}
		
		/* QUERY : returns a specific attachment */
		
		public CIIMMediaDescriptionHDO getAttachment(Long attachment_id)
		{
			CIIMMediaDescriptionHDO retval = null;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getAttachment(session, attachment_id);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getAttachment method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getAttachment method", e);
			} 
			
			return retval;		 			
		}
		
		public CIIMGroupAttachmentJSON getAttachmentAsJSON(Long attachment_id)
		{
			CIIMGroupAttachmentJSON retval = null;
			
			retval = aqc.convertCIIMMediaDescriptionToJSON(this.getAttachment(attachment_id));
			
			return retval;		 			
		}
		
		
		/* TRANSACTION : permanently deletes a specific attachment */
		
		public boolean deleteAttachment(Long attachment_id, HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null; 
			
			if(request != null && (request.isUserInRole(Constants.CIIM_EDITOR_ROLE) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					retval = atc.deleteAttachment(session, attachment_id);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in deleteAttachment method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with deleteAttachment method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION : removes an attachment from a group (this is not the same as deleting an attachment) */
		
		public void removeAttachment(String gid, Long attachment_id, HttpServletRequest request)
		{
			Session session = null;
			
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					atc.removeAttachment(session, gid, attachment_id);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in removeAttachment method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with removeAttachment method", e);
				} 	  
			}
		}
		
		/* TRANSACITON */
		
		public CIIMGroupAttachmentJSON setAttachmentLoadedText(Long attachment_id, Byte[] loadedText, HttpServletRequest request)
		{
			CIIMGroupAttachmentJSON retval = null;
			Session session = null;
			  
			if(request != null && (request.isUserInRole(Constants.CIIM_EDITOR_ROLE) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{	
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					retval = atc.setAttachmentLoadedText(session, attachment_id, loadedText);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in setAttachmentLoadedText method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with setAttachmentLoadedText method", e);
				} 	  
			}
			  
			return retval;
		}
		
		/* TRANSACTION : Creates a MIMSY media record */
		
		public synchronized boolean createMediaRecord(	Long attachment_id,	
														String caption,
														String credit_line, 
														String type, 
														String from_date, 
														String to_date,
														String holder, 
														String details,
														String small_path_abs,
														String small_path_rel,
														String medium_path_abs,
														String medium_path_rel,
														String large_path_abs,
														String large_path_rel,
														String donor_path_abs,
														String donor_path_rel,
														String relationship,
														HttpServletRequest request)
		{
			boolean retval = false;	  
			Session session = null;
			
			if(request != null && (request.isUserInRole(Constants.CIIM_EDITOR_ROLE) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					retval = atc.createMediaRecord(session, attachment_id, caption, credit_line, type, from_date, to_date, holder, details, small_path_abs, small_path_rel, medium_path_abs, medium_path_rel, large_path_abs, large_path_rel, donor_path_abs, donor_path_rel, relationship);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in setAttachmentLoadedText method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with setAttachmentLoadedText method", e);
				} 	  
			}
			
			return retval;
		}
		
		/** 
		 * IMAGE FORMATS 
		 */
		
		/* TRANSACTION : Creates an Image format for Image attachments to be resized to */
		
		public boolean createImgResizeFormat(	String name,
												Long base_height,
												Long base_width,
												String resize_dimension,
												Long small_size,
												Long medium_size,
												Long large_size,
												HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null;
			
			if(request != null && (request.isUserInRole(Constants.CIIM_EDITOR_ROLE) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					retval = atc.createImgResizeFormat(session, name, base_height, base_width, resize_dimension, small_size, medium_size, large_size);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in createImgResizeFormat method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with createImgResizeFormat method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION : Deletes format if format not in use */
		
		public boolean deleteImgResizeFormat(String name, HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null;
			
			if(request != null && (request.isUserInRole(Constants.CIIM_EDITOR_ROLE) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					retval = atc.deleteImgResizeFormat(session, name);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in deleteImgResizeFormat method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with deleteImgResizeFormat method", e);
				} 
			}
			
			return retval;
		}
		
		/* QUERY : return all image resize formats */
		
		public List<CIIMMediaFormatJSON> getImgResizeFormats()
		{
			List<CIIMMediaFormatJSON> retval = new ArrayList<CIIMMediaFormatJSON>();
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getImgResizeFormats(session);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getImgResizeFormats method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getImgResizeFormats method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : returns a specific image resize format */
		
		public CIIMImgResizeFormatHDO getImgResizeFormat(String name)
		{
			CIIMImgResizeFormatHDO retval = null;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getImgResizeFormat(session, name);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getImgResizeFormat method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getImgResizeFormat method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : returns all image formats that apply to the dimensions of a specified attachment */
		
		public List<CIIMMediaFormatJSON> getApplicableImgResizeFormats(Long attachment_id)
		{
			List<CIIMMediaFormatJSON> retval = new ArrayList<CIIMMediaFormatJSON>();
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				retval = aqc.getApplicableImgResizeFormats(session, attachment_id);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getApplicableImgResizeFormats method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getApplicableImgResizeFormats method", e);
			} 
			
			return retval;
		}
		
	
	/**
	 *  MIMSY Data Functions 
	 */
	
		/* QUERY : returns all objects for a specific group */
		
		public List<CIIMObjectJSON> getGroupObjects(String gid)
		{
			List<CIIMObjectJSON> retval = null;
			Session session = null;
			  
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = mqc.getGroupObjects(session, gid);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getGroupObjects method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getGroupObjects method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : returns all MIMSY items (objects et al) of a given status */
		
		public List<CIIMBaseMimsyJSON> getMimsyDataByStatus(DataStatusEnum status)
		{
			List<CIIMBaseMimsyJSON> retval = null;		 
			Session session = null;
			  
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = mqc.getMimsyDataByStatus(session, status);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getMimsyDataByStatus method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getMimsyDataByStatus method", e);
			} 
			
			return retval;	  
		}
		
		/* QUERY : Lookup specific Object */
		
		public CIIMObjectJSON getMimsyObject(String gid, String id)
		{
			CIIMObjectJSON retval = null;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = mqc.getMimsyObjectAsJSON(session, gid, id);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getMimsyObject method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getMimsyObject method", e);
			} 
			
			return retval;
		}
		
		/* TRANSACTION : */
		
		public boolean featureObject(String gid, Long id, boolean makeFeatured, HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null;
		  
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{	
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = mtc.featureObject(session, gid, id, makeFeatured);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in featureObject method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with featureObject method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION */
		
		public boolean boostObject(String gid, Long id, int boost_value, HttpServletRequest request)
		{  
			boolean retval = false;
			Session session = null;
		  
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{	
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = mtc.boostObject(session, gid, id, boost_value);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in boostObject method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with boostObject method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRASNSACTION */
		
		public boolean archiveObject(Long id, String gid, HttpServletRequest request)
		{
			boolean retval = false;
			Session session = null;
		  
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{	
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = mtc.archiveObject(session, id, gid);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in archiveObject method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with archiveObject method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION */
		
		public String deleteMimsyData(String id, HttpServletRequest request)
		{
			String retval = "Unable to process deletion.";
			Session session = null;
		  
			if(request != null && request.isUserInRole(Constants.CIIM_EDITOR_ROLE))
			{	
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					if(mtc.deleteMimsyData(session, id))
					{
						retval = "Deletion Successful.";
					}
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in deleteMimsyData method", he);
				} 
				catch (Exception e) 
				{
					retval = e.getMessage();
					log.error("[firstrun:1] Problem with deleteMimsyData method", e);
				} 
			}
			
			return retval;
		}
		
		/* TRANSACTION */
		
		public void updateObjectDataContext(MultivaluedMap<String, String> form_params, 
											HttpServletRequest request)
		{
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				mtc.updateObjectDataContext(session, form_params);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in cascade publication method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with cascade publication method", e);
			} 
		}
		
		/* QUERY */
		
		public List<CIIMObjectJSON> getObjectsBySearchParams(String gid, Integer search_field, String search_value)
		{
			List<CIIMObjectJSON> retval = null;
			Session session = null;
			
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				switch(search_field.intValue())
				{
					case 0 : retval = mqc.searchObjectsByObjectId(session, gid, search_value); break;
					case 1 : retval = mqc.searchObjectsByMimsyId(session, gid, search_value); break;
				  	case 2 : retval = mqc.searchObjectsBySummaryTitle(session, gid, search_value); break;
				  	default : retval = null; break;
				}
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getObjectsBySearchParams method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getObjectsBySearchParams method", e);
			} 
			
			return retval;
		}
		
		
		/* TRANSACTION */
		
		public CIIMObjectJSON addCIIMDataContextToGroup(String mimsy_id, String gid, HttpServletRequest request)
		{
			CIIMObjectJSON retval = null;
			  
			if(request != null && ((request.isUserInRole(Constants.CIIM_EDITOR_ROLE) && userHasPermissions(request, gid)) || request.isUserInRole(Constants.CIIM_ADMIN_ROLE)))
			{
				Session session = null;
				
				try 
				{
					session = SessionFactoryUtils.getSession(factory, true);
					
					retval = mtc.addCIIMDataContextToGroup(session, mimsy_id, gid);
				}
				catch (HibernateException he) 
				{
					log.error("[firstrun:1] Problem with query in addCIIMDataContextToGroup method", he);
				} 
				catch (Exception e) 
				{
					log.error("[firstrun:1]Problem with addCIIMDataContextToGroup method", e);
				} 
				
			}
			
			return retval;
		}
	
	/**
	 * 	Validation Functions 
	 */
	
		/* Query : returns a specific validation result */
		
		public ValidationResultJSON getValidationResult(String identifier)
		{
			ValidationResultJSON retval = null;			
			Session session = null;
			  
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = vqc.getValidationResult(session, identifier);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getValidationResult method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getValidationResult method", e);
			} 
			
			return retval;
		}
		
		/* Returns ALL Validation results from the mimsy extraction routine */
		
		public List<ValidationResultJSON> getMimsyValidationResults()
		{
			return this.getValidationResults("MimsyExtractRoutine");
		}
		
		/* Returns publishing errors for a specific group */
		
		public List<ValidationResultJSON> getPublicationValidationResults(String mimsy_identifier)
		{
			return this.getValidationResults("Group-" + mimsy_identifier);
		}
		
		/* QUERY : returns validations results according a specific bundle identifier */
		
		private List<ValidationResultJSON> getValidationResults(String bundle_identifier)
		{
			List<ValidationResultJSON> retval = new ArrayList<ValidationResultJSON>();
			
			Session session = null;
			  
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);
				
				retval = vqc.getValidationResults(session, bundle_identifier);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getValidationResult method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getValidationResult method", e);
			} 
			
			return retval;
		}
	
	/**
	 *  Security Functions 
	 */
	
		/* Checks to see if a user has edit permissions for a specific group */
			
		public boolean userHasPermissions(HttpServletRequest request, String gid)
		{
			boolean retval = false;
		  
			IdentityService ident_srv = (IdentityService) ctx.getBean("IdentityService");
	  
			if(request != null && request.getUserPrincipal() != null)
			{
				if( request.isUserInRole(Constants.CIIM_ADMIN_ROLE))
				{
					retval = true;
				}
				else
				{
					try
					{
						Long user_id = ident_srv.usernameToId(request.getUserPrincipal().getName());
						
						retval = IdentityServiceWrapper.hasPermission(ident_srv, user_id, Constants.CIIM_EDIT_GROUP_PERMISSION, Constants.TCN_CIIM_CURATED_GROUP, gid);	
					}
					catch(IdentityServiceException ise)
					{
						log.error("Error checking user permissions : " + ise);
					}
				}
			}	  
			return retval;
		}
		
	/**
	 * SCHEMA FUNCTIONS
	 */
		
		/* QUERY */
		
		public List<SchemaDefinitionJSON> getSchemas(MimsyDataTypeEnum type)
		{
			List<SchemaDefinitionJSON> retval = null;
			Session session = null;
			  
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);			
				retval = sqc.getSchemas(session,type);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getSchemas method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getSchemas method", e);
			} 
			
			return retval;
		}
		
		/* QUERY : GET ALL SCHEMAS */
		
		public List<SchemaDefinitionJSON> getAllSchemas()
		{
			List<SchemaDefinitionJSON> retval = null;
			Session session = null;
			  
			try 
			{
				session = SessionFactoryUtils.getSession(factory, true);			
				retval = sqc.getAllSchemas(session);
			}
			catch (HibernateException he) 
			{
				log.error("[firstrun:1] Problem with query in getSchemas method", he);
			} 
			catch (Exception e) 
			{
				log.error("[firstrun:1]Problem with getSchemas method", e);
			} 
			
			return retval;
		}
		
		
	/**
	 * HDO to JSON DTO convert Functions
	 */
		
		private CIIMGroupJSON convertHDOtoJSON(Session session, CIIMGroupHDO hdo, HttpServletRequest request)
		{
			CIIMGroupJSON retval = null;
			  
			if(hdo != null && hdo.getCuratedGroup() != null)
			{
				MimsyCuratedGroupHDO lCuratedGroup = hdo.getCuratedGroup();
				  	
				CIIMGroupContextHDO lGroupMetadata = hdo.getGroupContext();
				  	
			  	String longDescription = null;
			  	String topGroupEditorialStatus = null;
			  	if(lGroupMetadata != null)
			  	{
			  		longDescription = lGroupMetadata.getLongDescription();
			  	}
			  	if(hdo.getTopGroupEditorialStatus() != null)
			  	{
			  		topGroupEditorialStatus = hdo.getTopGroupEditorialStatus().toString();
			  	}
			  	//TODO : remove url param from JSON object????
			  	
			  	String originator = null;
			  	if(lCuratedGroup.getOriginator() != null)
			  	{
			  		originator = lCuratedGroup.getOriginator().toString();
			  	}
			  	
			    retval = new CIIMGroupJSON(	lCuratedGroup.getId().toString(), 			// String gid 
			    							lCuratedGroup.getName(),					// String group_name
			    							CIIMGroupJSON.HIERARCHY_NONE,				// int hier
			    							lCuratedGroup.getOwner(), 					// String owner
			    							"0", 										// String items
			    							lCuratedGroup.getLastUpdated(),				// String date
			    							lCuratedGroup.getPurpose(),					// String purpose
			    							hdo.getMgmtStatus().toString(),				// String valid
			    							hdo.getPublicationStatus().toString(),		// String published
			    							lCuratedGroup.getDescription(),				// String description
			    							longDescription, 							// String long_description
			    							originator,									// String origin
			    							lCuratedGroup.getMimsyIdentifier(),			// String Mimsy
			    							topGroupEditorialStatus,					// String Top group Editorial Status
			    							this.userHasPermissions(request, lCuratedGroup.getId().toString()),// boolean user can edit
			    							IdentityServiceWrapper.getAssignedEditors(session, lCuratedGroup.getId().toString()),
			    							lCuratedGroup.getDataStatus().toString());		// Data Status
			    
			    if(lGroupMetadata != null)
			    {
			    	if(lGroupMetadata.getSchema() != null)
			    	{
					    //add in the schema fields
					    SchemaDefinitionHDO schema_definition = lGroupMetadata.getSchema();
					    Map<SchemaElementHDO, SchemaOptionValueHDO> option_values = lGroupMetadata.getOptions();
					    
					    SchemaDefinitionJSON schema_json = SchemaDefinitionJSON.schemaDefinitionHDOtoJSON(schema_definition, option_values);
					    
					    retval.schema = schema_json;
			    	}
			    	if(lGroupMetadata.getObjectSchema() != null)
			    	{
			    		SchemaDefinitionJSON object_schema_json = SchemaDefinitionJSON.schemaDefinitionHDOtoJSON(lGroupMetadata.getObjectSchema());
					    
			    		retval.object_schema = object_schema_json;
			    	}
			    }
			}
		    
		    return retval;  
		}	
}


