Java tutorial
/******************************************************************************* * Copyright (c) 2009 David Harrison. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl-3.0.html * * Contributors: * David Harrison - initial API and implementation ******************************************************************************/ package com.sfs.whichdoctor.dao; import com.sfs.beans.BuilderBean; import com.sfs.beans.ObjectTypeBean; import com.sfs.dao.SFSDaoException; import com.sfs.whichdoctor.beans.IsbEntityBean; import com.sfs.whichdoctor.beans.IsbTransactionBean; import com.sfs.whichdoctor.beans.PersonBean; import com.sfs.whichdoctor.beans.RelationshipBean; import com.sfs.whichdoctor.beans.RotationBean; import com.sfs.whichdoctor.beans.SearchBean; import com.sfs.whichdoctor.beans.SearchResultsBean; import com.sfs.whichdoctor.beans.SupervisorBean; import com.sfs.whichdoctor.formatter.OutputFormatter; import com.sfs.whichdoctor.search.SearchDAO; import com.sfs.whichdoctor.search.WhichDoctorSearchDaoException; import java.sql.ResultSet; import java.sql.Timestamp; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import javax.annotation.Resource; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.jdbc.core.RowMapper; /** * The Class RelationshipDAOImpl. * * @author David Harrison */ public class RelationshipDAOImpl extends WhichDoctorBaseDAOImpl implements RelationshipDAO { /** The Constant DEFAULT_LIMIT. */ private static final int DEFAULT_LIMIT = 2; /** The Constant LARGE_LONG. */ private static final long LARGE_LONG = 10000000000L; /** The simple date format object. */ private final SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); /** The data logger. */ private static Logger dataLogger = Logger.getLogger(RelationshipDAOImpl.class); /** The previous rotation limit. */ private int previousRotationLimit = DEFAULT_LIMIT; /** The person dao. */ @Resource private PersonDAO personDAO; /** The isb transaction dao. */ @Resource private IsbTransactionDAO isbTransactionDAO; /** The isb entity dao. */ @Resource private IsbEntityDAO isbEntityDAO; /** The search dao. */ @Resource private SearchDAO searchDAO; /** * Spring injector to override the default number of months should be * referred back to in order to find previous rotations supervisors. - The * default is 2 months * * @param previousRotationLimitVal the previous rotation limit */ public final void setPreviousRotationLimit(final int previousRotationLimitVal) { this.previousRotationLimit = previousRotationLimitVal; } /** * Used to get a Collection of RelationshipBeans for a specified GUID. * * @param guid the guid * @param loadDetails the load details * @return the collection of relationship beans * @throws WhichDoctorDaoException the which doctor dao exception */ @SuppressWarnings("unchecked") public final Collection<RelationshipBean> load(final int guid, final BuilderBean loadDetails) throws WhichDoctorDaoException { dataLogger.info("Relationships for GUID: " + guid + " requested"); final String loadRelationships = this.getSQL().getValue("relationship/load") + " AND relationships.GUID = ?"; Collection<RelationshipBean> relationships = new ArrayList<RelationshipBean>(); try { relationships = this.getJdbcTemplateReader().query(loadRelationships, new Object[] { true, guid }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadRelationship(rs, loadDetails); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return relationships; } /** * Used to get a Collection of RelationshipBeans for a specified objecttype. * * @param objectType the ObjectTypeBean to load * @param loadDetails the load details * @return the collection< relationship bean> * * @throws WhichDoctorDaoException the which doctor dao exception */ @SuppressWarnings("unchecked") public final Collection<RelationshipBean> load(final ObjectTypeBean objectType, final BuilderBean loadDetails) throws WhichDoctorDaoException { dataLogger.info("Relationships for objectType: " + objectType.getObjectTypeId()); final String loadRelationships = this.getSQL().getValue("relationship/load") + " AND relationships.RelationshipTypeId = ?"; Collection<RelationshipBean> relationships = new ArrayList<RelationshipBean>(); try { relationships = this.getJdbcTemplateReader().query(loadRelationships, new Object[] { true, objectType.getObjectTypeId() }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadRelationship(rs, loadDetails); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return relationships; } /** * Returns a map of relationship names ordered by division -> type -> hierarchy. * * @param relationshipClass - the relationship class to search on * @param maximumHierarchy - the largest level of hierarchy to return * @return - A map of Division strings with a corresponding Map of supervisor * types and related hierarchies. * @throws WhichDoctorDaoException the which doctor dao exception */ public final TreeMap<String, TreeMap<String, Integer>> loadRelationships(final String relationshipClass, final int maximumHierarchy) throws WhichDoctorDaoException { dataLogger.info("Loading map of '" + relationshipClass + "' relationships types"); TreeMap<String, TreeMap<String, Integer>> supervisorMap = new TreeMap<String, TreeMap<String, Integer>>(); int max = maximumHierarchy + 1; Collection<RelationshipBean> relationships = loadSupervisors(relationshipClass); for (RelationshipBean rel : relationships) { if (rel.getHierarchy() > 0 && rel.getHierarchy() < max) { TreeMap<String, Integer> map = new TreeMap<String, Integer>(); if (supervisorMap.containsKey(rel.getDivision())) { map = supervisorMap.get(rel.getDivision()); } map.put(rel.getRelationshipType(), rel.getHierarchy()); supervisorMap.put(rel.getDivision(), map); } } return supervisorMap; } /** * Used to get a Collection of RelationshipBeans that are dependent on the * supplied GUID. * * @param guid the guid * @param loadDetails the load details * @return the collection< relationship bean> * * @throws WhichDoctorDaoException the which doctor dao exception */ @SuppressWarnings("unchecked") public final Collection<RelationshipBean> findDependencies(final int guid, final BuilderBean loadDetails) throws WhichDoctorDaoException { dataLogger.info("Dependent relationships for GUID: " + guid + " requested"); final String loadDependent = this.getSQL().getValue("relationship/findDependent"); Collection<RelationshipBean> relationships = new ArrayList<RelationshipBean>(); try { relationships = this.getJdbcTemplateReader().query(loadDependent, new Object[] { guid, true }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadRelationship(rs, loadDetails); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return relationships; } /** * Rebuilds the relationships for all active people in the database. * * @throws WhichDoctorDaoException the which doctor dao exception */ public final void rebuildRelationships() throws WhichDoctorDaoException { dataLogger.error("Rebuilding all relationships..."); /* Perform a people search to get a list of active people */ SearchBean search = this.searchDAO.initiate("person", null); search.setLimit(0); final StringBuffer outcome = new StringBuffer(); try { SearchResultsBean results = this.searchDAO.search(search); if (results != null) { Collection<Object> searchResults = results.getSearchResults(); for (Object personObj : searchResults) { try { PersonBean person = (PersonBean) personObj; final String result = rebuildRelationships(person.getGUID(), "Person"); if (StringUtils.isNotBlank(result)) { outcome.append("\n" + result); } } catch (Exception e) { dataLogger.error("Error rebuilding relationships " + "for person: " + e.getMessage()); } } } } catch (WhichDoctorSearchDaoException e) { dataLogger.error("Error rebuilding relationships: " + e.getMessage()); throw new WhichDoctorDaoException("Error rebuilding relationships: " + e.getMessage()); } dataLogger.error("Finished rebuilding all relationships"); dataLogger.error("Summary of activity: "); dataLogger.error(outcome.toString()); } /** * Rebuild the relationships for people who may have had their relationships * modified during the defined period of time. This function assumes that * relationships will be rebuilt when entries are created, modified or * deleted. This really just checks rotations that have started or finished * within the defined period of time. * * @param startDate the start date * @param endDate the end date * * @throws WhichDoctorDaoException the which doctor dao exception */ public final void rebuildRelationships(final Date startDate, final Date endDate) throws WhichDoctorDaoException { if (startDate == null) { throw new WhichDoctorDaoException("The start date cannot be null"); } if (endDate == null) { throw new WhichDoctorDaoException("The end date cannot be null"); } // A map to store the potentially modified people GUIDs HashMap<Integer, Integer> peopleGUIDs = new HashMap<Integer, Integer>(); // Perform a search for rotations that started between the period of // time defined by the startDate and endDate parameters. try { SearchBean search = this.searchDAO.initiate("rotation", null); search.setLimit(0); BuilderBean load = new BuilderBean(); load.setParameter("SUPERVISORS", true); RotationBean criteria = (RotationBean) search.getSearchCriteria(); RotationBean constraints = (RotationBean) search.getSearchConstraints(); criteria.setStartDate(startDate); constraints.setStartDate(endDate); search.setSearchCriteria(criteria); search.setSearchConstraints(constraints); SearchResultsBean results = this.searchDAO.search(search, load); if (results != null) { Collection<Object> rotations = results.getSearchResults(); for (Object objRotation : rotations) { RotationBean rotation = (RotationBean) objRotation; if (rotation.getPersonId() > 0) { peopleGUIDs.put(rotation.getPersonId(), 0); } if (rotation.getSupervisors() != null) { for (SupervisorBean sup : rotation.getSupervisors()) { if (sup.getPersonGUID() > 0) { peopleGUIDs.put(sup.getPersonGUID(), 0); } } } } } } catch (WhichDoctorSearchDaoException wse) { dataLogger.error("Error performing search for recently started " + "rotations: " + wse.getMessage()); } // Perform a search for rotations that ended between the period of time // defined by the startDate and endDate parameters. try { SearchBean search = this.searchDAO.initiate("rotation", null); search.setLimit(0); BuilderBean load = new BuilderBean(); load.setParameter("SUPERVISORS", true); RotationBean criteria = (RotationBean) search.getSearchCriteria(); RotationBean constraints = (RotationBean) search.getSearchConstraints(); criteria.setEndDate(startDate); constraints.setEndDate(endDate); search.setSearchCriteria(criteria); search.setSearchConstraints(constraints); SearchResultsBean results = this.searchDAO.search(search, load); if (results != null) { Collection<Object> rotations = results.getSearchResults(); for (Object objRotation : rotations) { RotationBean rotation = (RotationBean) objRotation; if (rotation.getPersonId() > 0) { peopleGUIDs.put(rotation.getPersonId(), 0); } if (rotation.getSupervisors() != null) { for (SupervisorBean sup : rotation.getSupervisors()) { if (sup.getPersonGUID() > 0) { peopleGUIDs.put(sup.getPersonGUID(), 0); } } } } } } catch (WhichDoctorSearchDaoException wse) { dataLogger.error("Error performing search for recently started " + "rotations: " + wse.getMessage()); } // With the searches complete iterate through the map and rebuild each // of the relationships. for (Integer personGUID : peopleGUIDs.keySet()) { try { dataLogger.info("Rebuilding relationship for person GUID: " + personGUID); this.rebuildRelationships(personGUID, "Person"); } catch (WhichDoctorDaoException wde) { dataLogger.error( "Error updating the relationship for person GUID " + personGUID + ": " + wde.getMessage()); } } } /** * Rebuilds the relationship index for the specified GUID. * * @param guid the guid * @param type the type * @return the string * * @throws WhichDoctorDaoException the which doctor dao exception */ public final String rebuildRelationships(final int guid, final String type) throws WhichDoctorDaoException { String result = ""; // Load the existing relationships for this object Collection<RelationshipBean> existingRelationships = load(guid, new BuilderBean()); Collection<RelationshipBean> updatedRelationships = new ArrayList<RelationshipBean>(); // Begin the ISB transaction */ IsbTransactionBean isbTransaction = this.isbTransactionDAO.begin(guid); if (StringUtils.equalsIgnoreCase(type, "Person")) { /* Load the person specified by the GUID */ BuilderBean loadDetails = new BuilderBean(); loadDetails.setParameter("MEMBERSHIP", true); loadDetails.setParameter("TRAINING_ROTATIONS", true); Collection<RelationshipBean> changedRelationships = new ArrayList<RelationshipBean>(); Collection<RotationBean> priorRotations = new ArrayList<RotationBean>(); PersonBean person = null; try { person = this.personDAO.loadGUID(guid, loadDetails); } catch (Exception e) { dataLogger.error("Error loading person " + guid + ": " + e.getMessage()); } if (person == null) { person = new PersonBean(); } Collection<RotationBean> rotations = person.getRotations(); if (rotations == null) { rotations = new ArrayList<RotationBean>(); } Date currentDate = Calendar.getInstance().getTime(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MONTH, 0 - this.previousRotationLimit); final Date limitMonthsAgo = calendar.getTime(); for (RotationBean rotation : rotations) { try { /* Is this rotation currently taking place? */ if (rotation.getStartDate().compareTo(currentDate) <= 0 && rotation.getEndDate().compareTo(currentDate) >= 0) { dataLogger.debug("The rotation is taking place now"); dataLogger.debug("Rotation supervisor count: " + rotation.getSupervisors().size()); for (SupervisorBean supervisor : rotation.getSupervisors()) { RelationshipBean relationship = build(guid, supervisor.getPerson(), supervisor.getRelationshipClass(), supervisor.getRelationshipType(), rotation.getEndDate(), rotation.getGUID()); changedRelationships.add(relationship); } } else { // If not currently taking place did it end in the // time limit. If so add to prior rotations if (rotation.getEndDate().compareTo(limitMonthsAgo) > 0) { priorRotations.add(rotation); } } } catch (Exception e) { dataLogger.error( "Error processing rotation for person (" + person.getGUID() + "): " + e.getMessage()); } } // A trainee requires that all supervisor roles are satisfied Collection<RelationshipBean> supervisors = new ArrayList<RelationshipBean>(); Collection<RelationshipBean> otherRelationships = new ArrayList<RelationshipBean>(); // Divide the relationships between supervisors and others for (RelationshipBean relationship : changedRelationships) { dataLogger.debug("Relationship class: " + relationship.getRelationshipClass()); if (StringUtils.endsWith(relationship.getRelationshipClass(), "Supervisor") && StringUtils.isNotBlank(relationship.getISBMapping())) { // The relationship is a supervisor and has an ISB mapping supervisors.add(relationship); } else { dataLogger.debug("'Other' relationship processed"); otherRelationships.add(relationship); } } // Construct the full list of required supervisors Map<Integer, RelationshipBean> fullSupervisorMap = this.buildFullSupervisorMap(supervisors); if (fullSupervisorMap.size() == 0) { // No supervisors exist - try loading some from the past fullSupervisorMap = loadPriorSupervisorMap(priorRotations); } // Add the relationships from the full supervisors map for (Integer hierarchy : fullSupervisorMap.keySet()) { RelationshipBean relationship = fullSupervisorMap.get(hierarchy); updatedRelationships.add(relationship); } // Add the relationships from the other relationships collection for (RelationshipBean relationship : otherRelationships) { updatedRelationships.add(relationship); } result = update(existingRelationships, updatedRelationships); } /* Commit the ISB transaction */ this.isbTransactionDAO.commit(isbTransaction); return result; } /** * Generates a map of supervisors for a rotation based on their hierarchy. * This function ensures all required supervisor positions are filled. * * @param rotation the rotation * * @return the supervisor map */ public final TreeMap<Integer, RelationshipBean> getSupervisorMap(final RotationBean rotation) { Collection<RelationshipBean> supervisors = new ArrayList<RelationshipBean>(); if (rotation != null && rotation.getSupervisors() != null) { for (SupervisorBean supervisor : rotation.getSupervisors()) { RelationshipBean relationship = build(rotation.getPersonId(), supervisor.getPerson(), supervisor.getRelationshipClass(), supervisor.getRelationshipType(), rotation.getEndDate(), rotation.getGUID()); supervisors.add(relationship); } } return buildFullSupervisorMap(supervisors); } /** * Given list of prior rotations GUID and build a supervisor map. * * @param priorRotations the prior rotations * * @return the tree map< integer, relationship bean> */ private TreeMap<Integer, RelationshipBean> loadPriorSupervisorMap( final Collection<RotationBean> priorRotations) { TreeMap<Integer, RelationshipBean> supervisorMap = new TreeMap<Integer, RelationshipBean>(); TreeMap<Long, RotationBean> orderedRotations = new TreeMap<Long, RotationBean>(); for (RotationBean rotation : priorRotations) { long key = LARGE_LONG - rotation.getEndDate().getTime(); orderedRotations.put(key, rotation); } for (Long key : orderedRotations.keySet()) { RotationBean rotation = orderedRotations.get(key); dataLogger.info("End date: " + rotation.getEndDate()); if (supervisorMap.size() == 0) { supervisorMap = getSupervisorMap(rotation); } } return supervisorMap; } /** * Generates a map of supervisors based on their hierarchy. This function * ensures all required supervisor positions are filled. * * @param supervisors as a collection of RelationshipBeans * * @return the tree map< integer, relationship bean> */ private TreeMap<Integer, RelationshipBean> buildFullSupervisorMap( final Collection<RelationshipBean> supervisors) { TreeMap<Integer, RelationshipBean> fullSupervisorMap = new TreeMap<Integer, RelationshipBean>(); TreeMap<Integer, RelationshipBean> btSupervisorMap = new TreeMap<Integer, RelationshipBean>(); if (supervisors != null) { String relationshipClass = ""; for (RelationshipBean relationship : supervisors) { if (StringUtils.startsWithIgnoreCase(relationship.getRelationshipClass(), "Basic")) { // Only one relationship per basic training hierarchy-level is allowed if (dataLogger.isDebugEnabled()) { dataLogger.debug("Relationship: " + relationship.getRelationshipType()); dataLogger.debug("Hierarchy: " + relationship.getHierarchy()); } relationshipClass = relationship.getRelationshipClass(); btSupervisorMap.put(relationship.getHierarchy(), relationship); } } // If a basic training supervisor exists build a full map if (btSupervisorMap.size() > 0) { dataLogger.debug("At least one basic training supervisor exists"); dataLogger.debug("Relationship class: " + relationshipClass); fullSupervisorMap = buildInheritedMap(relationshipClass, btSupervisorMap); } for (RelationshipBean relationship : supervisors) { if (!StringUtils.startsWithIgnoreCase(relationship.getRelationshipClass(), "Basic")) { String heirarchy = relationship.getHierarchy() + "00" + relationship.getReferenceGUID(); int index = Integer.parseInt(heirarchy); fullSupervisorMap.put(index, relationship); } } } dataLogger.debug("Supervisor map size: " + fullSupervisorMap.size()); return fullSupervisorMap; } /** * Builds the inherited map. * * @param relationshipClass the relationship class * @param relationshipMap the relationship map * @return the tree map */ private TreeMap<Integer, RelationshipBean> buildInheritedMap(final String relationshipClass, final TreeMap<Integer, RelationshipBean> relationshipMap) { TreeMap<Integer, RelationshipBean> fullSupervisorMap = new TreeMap<Integer, RelationshipBean>(); // Load the supervisor type map TreeMap<Integer, String> types = null; try { types = loadSupervisorRelationships(relationshipClass); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error loading the supervisor object types: " + wde.getMessage()); } int maxHierarchy = 0; if (types != null) { dataLogger.debug("Supervisor relationships: " + types.size()); for (Integer hierarchy : types.keySet()) { // Set the maxiumum hierarchy value by getting the last key if (hierarchy > maxHierarchy) { maxHierarchy = hierarchy; } } } dataLogger.debug("Maximum hierarchy: " + maxHierarchy); for (Integer hierarchy : types.keySet()) { final String typeName = types.get(hierarchy); if (dataLogger.isDebugEnabled()) { dataLogger.debug("Hierarchy key is: " + hierarchy); dataLogger.debug("Type is: " + typeName); } if (!relationshipMap.containsKey(hierarchy)) { // If the relationship is missing we need to find one RelationshipBean newSup = null; for (int i = 1; i < maxHierarchy + 1; i++) { dataLogger.debug("Looking up key: " + i); if (newSup == null && relationshipMap.containsKey(i)) { RelationshipBean exSup = relationshipMap.get(i); newSup = exSup.clone(); newSup.setRelationshipType(typeName); } } if (newSup != null) { if (dataLogger.isDebugEnabled()) { dataLogger.debug("Adding a new supervisor"); dataLogger.debug("GUID: " + newSup.getGUID()); dataLogger.debug("Identifier: " + newSup.getIdentifier()); dataLogger.debug("Relationship Class: " + newSup.getRelationshipClass()); dataLogger.debug("Relationship Type: " + newSup.getRelationshipType()); } fullSupervisorMap.put(hierarchy, newSup); } } else { RelationshipBean extSup = relationshipMap.get(hierarchy); if (dataLogger.isDebugEnabled()) { dataLogger.debug("Adding an existing supervisor"); dataLogger.debug("GUID: " + extSup.getGUID()); dataLogger.debug("Identifier: " + extSup.getIdentifier()); dataLogger.debug("Relationship Class: " + extSup.getRelationshipClass()); dataLogger.debug("Relationship Type: " + extSup.getRelationshipType()); } fullSupervisorMap.put(hierarchy, extSup); } } return fullSupervisorMap; } /** * Iterate through the existing relationships and see what is different to * the updated ones. * * @param existingRelationships the existing relationships * @param updatedRelationships the updated relationships * @return the string */ private String update(final Collection<RelationshipBean> existingRelationships, final Collection<RelationshipBean> updatedRelationships) { HashMap<String, RelationshipBean> existingMap = new HashMap<String, RelationshipBean>(); HashMap<String, RelationshipBean> updatedMap = new HashMap<String, RelationshipBean>(); for (RelationshipBean relationship : existingRelationships) { final String key = buildKey(relationship); dataLogger.debug("Adding existing relationship: " + key); existingMap.put(key, relationship); } for (RelationshipBean relationship : updatedRelationships) { final String key = buildKey(relationship); dataLogger.debug("Adding updated relationship: " + key); updatedMap.put(key, relationship); } dataLogger.debug("Existing map size: " + existingMap.size()); dataLogger.debug("Updated map size: " + updatedMap.size()); final StringBuffer summary = new StringBuffer(); for (String key : existingMap.keySet()) { dataLogger.debug("Existing key: " + key); // No need to update relationships that have not changed if (!updatedMap.containsKey(key)) { // The updated map does not contain this entry // Delete this relationship reference final RelationshipBean relationship = existingMap.get(key); try { delete(relationship); // Load the person final PersonBean person = this.personDAO.loadGUID(relationship.getGUID()); final StringBuffer info = new StringBuffer(); info.append("Deleted a relationship to "); info.append(person.getPersonIdentifier()); info.append(". Person "); info.append(relationship.getIdentifier()); info.append(" was their "); info.append(relationship.getRelationshipClass()); info.append(" - "); info.append(relationship.getRelationshipType()); dataLogger.info(info.toString()); summary.append(info.toString() + "\n"); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error deleting relationship: " + wde.getMessage()); } } } for (String key : updatedMap.keySet()) { dataLogger.debug("Updated key: " + key); // No need to update relationships that have not changed if (!existingMap.containsKey(key)) { // The relationship does not exist - create the relationship RelationshipBean relationship = updatedMap.get(key); try { create(relationship); // Load the person final PersonBean person = this.personDAO.loadGUID(relationship.getGUID()); final StringBuffer info = new StringBuffer(); info.append("Created a relationship to "); info.append(person.getPersonIdentifier()); info.append(". Person "); info.append(relationship.getIdentifier()); info.append(" is their "); info.append(relationship.getRelationshipClass()); info.append(" - "); info.append(relationship.getRelationshipType()); dataLogger.info(info.toString()); summary.append(info.toString() + "\n"); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error creating relationship: " + wde.getMessage()); } } } return summary.toString(); } /** * Builds the RelationshipBean. * * @param guid the guid * @param person the person * @param className the class name * @param type the type * @param rotationEndDate the rotation end date * * @return the relationship bean */ private RelationshipBean build(final int guid, final PersonBean person, final String className, final String type, final Date rotationEndDate, final int rotationGUID) { RelationshipBean relationship = new RelationshipBean(); relationship.setGUID(guid); relationship.setReferenceGUID(person.getGUID()); relationship.setRelationshipClass(className); relationship.setRelationshipType(type); relationship.setIdentifier(String.valueOf(person.getPersonIdentifier())); relationship.setName(OutputFormatter.toFormattedName(person)); relationship.setPerson(person); relationship.setEndDate(rotationEndDate); relationship.setRotationGUID(rotationGUID); // Load the objecttype for this relationship try { ObjectTypeBean objecttype = this.getObjectTypeDAO().load("Relationship Type", type, className); if (objecttype != null) { relationship.setISBMapping(objecttype.getLdapMapping(1)); relationship.setHierarchy((int) objecttype.getValue()); } } catch (SFSDaoException sde) { dataLogger.info("Error loading objecttype for relationship: " + sde.getMessage()); } return relationship; } /** * Builds the key. * * @param relationship the relationship * * @return the string */ private String buildKey(final RelationshipBean relationship) { String endDate = ""; if (relationship.getEndDate() != null) { endDate = df.format(relationship.getEndDate()); } String key = relationship.getGUID() + "_" + relationship.getReferenceGUID() + "_" + relationship.getRelationshipClass() + "_" + relationship.getRelationshipType() + "_" + endDate; return key; } /** * Creates the. * * @param relationship the relationship * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ private boolean create(final RelationshipBean relationship) throws WhichDoctorDaoException { return update(relationship, true); } /** * Delete. * * @param relationship the relationship * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ private boolean delete(final RelationshipBean relationship) throws WhichDoctorDaoException { return update(relationship, false); } /** * Update. * * @param relationship the relationship * @param status the status * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ private boolean update(final RelationshipBean relationship, final boolean status) throws WhichDoctorDaoException { boolean success = false; // Get the relationship Type int relationshipTypeId = 0; try { ObjectTypeBean object = this.getObjectTypeDAO().load("Relationship Type", relationship.getRelationshipType(), relationship.getRelationshipClass()); relationshipTypeId = object.getObjectTypeId(); } catch (Exception e) { throw new WhichDoctorDaoException("Error loading relationship type: " + e.getMessage()); } Timestamp sqlTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); final int updateCount = this.getJdbcTemplateWriter().update(this.getSQL().getValue("relationship/update"), new Object[] { relationship.getGUID(), relationship.getReferenceGUID(), relationshipTypeId, relationship.getIdentifier(), relationship.getName(), relationship.getEndDate(), relationship.getRotationGUID(), sqlTimeStamp, status, relationship.getIdentifier(), relationship.getName(), relationship.getEndDate(), relationship.getRotationGUID(), sqlTimeStamp, status }); if (updateCount > 0) { success = true; // With the relationships updated check that // all the related entities are on the ISB try { // See if this the GUID of this relationship is an ISB entity // Load the current list of relationships this GUID has Collection<RelationshipBean> relationships = load(relationship.getGUID(), new BuilderBean()); /* Load the references to this relationship's GUID on the ISB */ dataLogger.debug("Loading the relationships for GUID: " + relationship.getGUID()); Collection<IsbEntityBean> entities = new ArrayList<IsbEntityBean>(); SearchBean search = searchDAO.initiate("isbentity", null); IsbEntityBean searchCriteria = (IsbEntityBean) search.getSearchCriteria(); searchCriteria.setGUID(relationship.getGUID()); search.setSearchCriteria(searchCriteria); search.setLimit(0); SearchResultsBean results = searchDAO.search(search); if (results != null && results.getSearchResults() != null) { for (Object result : results.getSearchResults()) { IsbEntityBean isbEntity = (IsbEntityBean) result; entities.add(isbEntity); } } // Iterate through the relationships // and entities to ensure sibling entities exist for (RelationshipBean related : relationships) { // The relationship has an ISB mapping if (StringUtils.isNotBlank(related.getISBMapping())) { for (IsbEntityBean entity : entities) { dataLogger.debug("Creating entity GUID: " + related.getGUID() + " for target: " + entity.getTarget()); try { // Create this related entity // on the ISB (if exists won't be created) IsbEntityBean newEntity = new IsbEntityBean(); newEntity.setGUID(related.getReferenceGUID()); newEntity.setIdentifier(related.getIdentifier()); newEntity.setName(related.getName()); newEntity.setObjectType("Person"); newEntity.setTarget(entity.getTarget()); this.isbEntityDAO.create(newEntity, false); } catch (Exception e) { dataLogger.error("Error creating related ISB " + "entity: " + e.getMessage()); } } } } } catch (Exception e) { dataLogger.error("Error checking related entities on the ISB: " + e.getMessage()); } } return success; } /** * Load relationship from the supplied dataset. * * @param rs the rs * @param loadDetails the load details * @return the relationship bean * * @throws SQLException the SQL exception */ private RelationshipBean loadRelationship(final ResultSet rs, final BuilderBean loadDetails) throws SQLException { // Create relationship bean and fill with dataset info. RelationshipBean relationship = new RelationshipBean(); relationship.setGUID(rs.getInt("GUID")); relationship.setReferenceGUID(rs.getInt("ReferenceGUID")); relationship.setRelationshipClass(rs.getString("RelationshipClass")); relationship.setRelationshipType(rs.getString("RelationshipType")); relationship.setHierarchy(rs.getInt("Hierarchy")); relationship.setISBMapping(rs.getString("ISBMapping")); relationship.setIdentifier(rs.getString("Identifier")); relationship.setName(rs.getString("Name")); relationship.setRotationGUID(rs.getInt("RotationGUID")); try { relationship.setEndDate(rs.getDate("EndDate")); } catch (SQLException e) { dataLogger.info("Error parsing EndDate date: " + e.getMessage()); } try { relationship.setModifiedDate(rs.getDate("Modified")); } catch (SQLException e) { dataLogger.info("Error parsing Modified date: " + e.getMessage()); } if (loadDetails.getBoolean("PERSON")) { try { PersonBean person = this.personDAO.loadGUID(relationship.getGUID()); relationship.setPerson(person); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error loading person for relationship: " + wde.getMessage()); } } if (loadDetails.getBoolean("RELATED_PERSON")) { try { PersonBean person = this.personDAO.loadGUID(relationship.getReferenceGUID()); relationship.setRelatedPerson(person); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error loading related person for relationship: " + wde.getMessage()); } } return relationship; } /** * Load supervisor relationships. * * @param relationshipClass the relationship class * @return the tree map<integer, string> * * @throws WhichDoctorDaoException the which doctor dao exception */ private TreeMap<Integer, String> loadSupervisorRelationships(final String relationshipClass) throws WhichDoctorDaoException { dataLogger.info("Loading map of supervisor relationships types"); TreeMap<Integer, String> supervisorMap = new TreeMap<Integer, String>(); Collection<RelationshipBean> relationships = loadSupervisors(relationshipClass); for (RelationshipBean relationship : relationships) { if (relationship.getHierarchy() > 0 && !supervisorMap.containsKey(relationship.getHierarchy())) { supervisorMap.put(relationship.getHierarchy(), relationship.getRelationshipType()); } } return supervisorMap; } /** * A private function to load the collection of supervisor * RelationshipBeans. * * @param relationshipClass the relatinship class * @return the collection< relationship bean> */ @SuppressWarnings("unchecked") private Collection<RelationshipBean> loadSupervisors(final String relationshipClass) { final String loadSupervisors = this.getSQL().getValue("relationship/loadSupervisors"); Collection<RelationshipBean> relationships = new ArrayList<RelationshipBean>(); try { relationships = this.getJdbcTemplateReader().query(loadSupervisors, new Object[] { "Relationship Type", relationshipClass }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { RelationshipBean rel = new RelationshipBean(); rel.setRelationshipClass(rs.getString("RelationshipClass")); rel.setRelationshipType(rs.getString("RelationshipType")); rel.setDivision(rs.getString("Division")); rel.setHierarchy(rs.getInt("Hierarchy")); return rel; } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return relationships; } }