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.beans.PrivilegesBean; import com.sfs.beans.UserBean; import com.sfs.whichdoctor.beans.GroupBean; import com.sfs.whichdoctor.beans.IsbEntityBean; import com.sfs.whichdoctor.beans.ItemBean; import com.sfs.whichdoctor.beans.PersonBean; import com.sfs.whichdoctor.beans.RelationshipBean; import com.sfs.whichdoctor.beans.SearchBean; import com.sfs.whichdoctor.beans.SearchResultsBean; 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.util.ArrayList; import java.util.Calendar; import java.util.Collection; 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.DataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.jdbc.core.RowMapper; /** * The Class IsbEntityDAOImpl. */ public class IsbEntityDAOImpl extends BaseDAOImpl implements IsbEntityDAO { /** The data logger. */ private static Logger dataLogger = Logger.getLogger(IsbEntityDAOImpl.class); /** The Constant WEIGHTING. */ private static final int WEIGHTING = 10; /** The Constant PERMISSION. */ private static final String PERMISSION = "groups"; /** The Constant ITEMTYPE. */ private static final String ITEMTYPE = "Group"; /** The mandatory groups. */ private Map<Integer, String> mandatoryGroups; /** The group dao. */ @Resource private GroupDAO groupDAO; /** The item dao. */ @Resource private ItemDAO itemDAO; /** The person dao. */ @Resource private PersonDAO personDAO; /** The search dao. */ @Resource private SearchDAO searchDAO; /** The relationship dao. */ @Resource private RelationshipDAO relationshipDAO; /** The isb transaction dao. */ @Resource private IsbTransactionDAO isbTransactionDAO; /** * Sets the mandatory groups that an ISB entity must be a part of. * Key -> The GUID (int) of the group. * Value -> The name (string) of the group. * * @param mandatoryGroupsVal the mandatory groups */ public final void setMandotoryGroups(final Map<Integer, String> mandatoryGroupsVal) { this.mandatoryGroups = mandatoryGroupsVal; } /** * Loads an IsbEntityBean for a specified id. * * @param id the id * * @return the isb entity bean * * @throws WhichDoctorDaoException the which doctor dao exception */ public final IsbEntityBean load(final int id) throws WhichDoctorDaoException { dataLogger.info("ISB entitiy for Id: " + id); IsbEntityBean entity = null; try { entity = (IsbEntityBean) this.getJdbcTemplateReader().queryForObject( this.getSQL().getValue("isbentity/loadId"), new Object[] { id }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadIsbEntity(rs); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return entity; } /** * Loads an IsbEntityBean for an identified target/guid combination. If none * found returns null * * @param target the target * @param guid the guid * * @return the isb entity bean * * @throws WhichDoctorDaoException the which doctor dao exception */ public final IsbEntityBean load(final String target, final int guid) throws WhichDoctorDaoException { if (target == null) { throw new NullPointerException("The supplied target cannot be null"); } dataLogger.info("ISB entities for target: " + target + " requested"); IsbEntityBean entity = null; try { entity = (IsbEntityBean) this.getJdbcTemplateReader().queryForObject( this.getSQL().getValue("isbentity/loadTargetId"), new Object[] { target, guid, true }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadIsbEntity(rs); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return entity; } /** * Loads an entity bean for an identified target/identifier combination. * * @param target the target * @param identifier the identifier * * @return the isb entity bean * * @throws WhichDoctorDaoException the which doctor dao exception */ public final IsbEntityBean load(final String target, final String identifier) throws WhichDoctorDaoException { if (target == null) { throw new NullPointerException("The supplied target cannot be null"); } if (identifier == null) { throw new NullPointerException("The supplied identifier cannot be null"); } dataLogger.info("ISB entities for target: " + target + " requested"); IsbEntityBean entity = null; try { entity = (IsbEntityBean) this.getJdbcTemplateReader().queryForObject( this.getSQL().getValue("isbentity/loadTargetIdentifier"), new Object[] { target, identifier, true }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadIsbEntity(rs); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for search: " + ie.getMessage()); } return entity; } /** * Loads all the entity beans for a specified identifier. * * @param guid the entity's GUID * * @return the collection of isb entity beans * * @throws WhichDoctorDaoException the which doctor dao exception */ public final Collection<IsbEntityBean> loadAll(final int guid) throws WhichDoctorDaoException { dataLogger.info("ISB entities for GUID: " + guid + " requested"); final Collection<IsbEntityBean> isbEntities = new ArrayList<IsbEntityBean>(); final SearchBean isbSearch = searchDAO.initiate("isbentity", new UserBean()); isbSearch.setLimit(0); IsbEntityBean entity = (IsbEntityBean) isbSearch.getSearchCriteria(); entity.setGUID(guid); isbSearch.setSearchCriteria(entity); try { final SearchResultsBean isbResults = searchDAO.search(isbSearch); if (isbResults != null && isbResults.getSearchResults() != null) { for (Object objResult : isbResults.getSearchResults()) { IsbEntityBean isbEntity = (IsbEntityBean) objResult; isbEntities.add(isbEntity); } } } catch (WhichDoctorSearchDaoException wdse) { dataLogger.error("Error loading ISB entities: " + wdse.getMessage()); } return isbEntities; } /** * Loads an IsbEntityBean for a specified id. * * @param entity the ISB entity * @param refresh the identity on the ISB * * @return the isb entity bean * * @throws WhichDoctorDaoException the which doctor dao exception */ public final boolean create(final IsbEntityBean entity, final boolean refresh) throws WhichDoctorDaoException { return create(entity, refresh, new UserBean(), new PrivilegesBean(), true); } /** * Creates the IsbEntityBean. * * @param entity the entity * @param refresh the ISB entity * @param checkUser the user * @param privileges the privileges * @param internalModification the internal modification * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ public final boolean create(final IsbEntityBean entity, final boolean refresh, final UserBean checkUser, final PrivilegesBean privileges, final boolean internalModification) throws WhichDoctorDaoException { boolean success = false; if (!privileges.getPrivilege(checkUser, "systemAdmin", "modify") && !internalModification) { throw new WhichDoctorDaoException("Insufficient user credentials to create isb entity"); } boolean entityExists = false; // Check if this entity exists on the ISB already // if it does first remove it, then re-add it (refresh) try { IsbEntityBean existingEntity = this.load(entity.getTarget(), entity.getGUID()); if (existingEntity != null && existingEntity.getGUID() > 0) { entityExists = true; } } catch (Exception e) { dataLogger.info("Error checking if ISB entity exists: " + e.getMessage()); } boolean createEntry = true; if (entityExists) { dataLogger.debug("Entity exists"); if (refresh) { // The entry exists but refresh is true - delete and create dataLogger.debug("Deleting the existing entity"); try { this.isbTransactionDAO.deleteInstance(entity.getGUID(), entity.getObjectType(), entity.getTarget()); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error removing ISB entry: " + wde.getMessage()); } } else { // Entry exists but refresh is set to false - do nothing createEntry = false; } } if (createEntry) { // Check that the identity belongs to any mandatory groups checkMandatoryGroups(entity.getGUID(), false, privileges); // Update the internal modification time. success = update(entity, true, true, true); // Post a 'create' message on the ISB for the identified object this.isbTransactionDAO.createInstance(entity.getGUID(), entity.getObjectType(), entity.getTarget()); } return success; } /** * Modify the IsbEntityBean. * * @param entity the entity * @param checkUser the user * @param privileges the privileges * @param internalModification the internal modification * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ public final boolean modify(final IsbEntityBean entity, final UserBean checkUser, final PrivilegesBean privileges, final boolean internalModification) throws WhichDoctorDaoException { if (!internalModification && !privileges.getPrivilege(checkUser, "systemAdmin", "modify")) { throw new WhichDoctorDaoException("Insufficient user credentials to modify isb entity"); } return update(entity, true, false, internalModification); } /** * Delete the IsbEntityBean. * * @param entity the entity * @param checkUser the user * @param privileges the privileges * @param internalModification the internal modification * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ public final boolean delete(final IsbEntityBean entity, final UserBean checkUser, final PrivilegesBean privileges, final boolean internalModification) throws WhichDoctorDaoException { return delete(entity, checkUser, privileges, false, internalModification); } /** * Delete the IsbEntityBean. * * @param entity the entity * @param checkUser the user * @param privileges the privileges * @param recursiveDelete the recursive delete * @param internalModification the internal modification * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ public final boolean delete(final IsbEntityBean entity, final UserBean checkUser, final PrivilegesBean privileges, final boolean recursiveDelete, final boolean internalModification) throws WhichDoctorDaoException { if (!internalModification && !privileges.getPrivilege(checkUser, "systemAdmin", "modify")) { throw new WhichDoctorDaoException("Insufficient user credentials to delete isb entity"); } // Check to see if other ISB entities depend on this entity. If they do // and recursiveDelete is not set to true throw an exception as it is // not possible cannot delete a dependent object. Collection<IsbEntityBean> dependents = new ArrayList<IsbEntityBean>(); try { // Search to see if any relationships depend on this entity Collection<RelationshipBean> dependencies = this.relationshipDAO.findDependencies(entity.getGUID(), new BuilderBean()); dataLogger.debug("Dependent relationships: " + dependencies.size()); // Check if any of these related objects exist on the ISB for (RelationshipBean relationship : dependencies) { dataLogger.debug("Processing relationship: " + relationship.getGUID()); // Is the relationship has an ISB mapping perform check if (StringUtils.isNotBlank(relationship.getISBMapping())) { // Check if this IsbEntity exists on the specified target IsbEntityBean depEntity = load(entity.getTarget(), relationship.getGUID()); if (depEntity != null) { dependents.add(depEntity); } } } } catch (Exception e) { dataLogger.error("Error checking dependencies for entity deletion: " + e.getMessage()); throw new WhichDoctorDaoException("Error checking dependencies for entity deletion: " + e.getMessage()); } if (dependents.size() > 0) { // Depend entities exist on the bus if (recursiveDelete) { for (IsbEntityBean depEntity : dependents) { // Delete this dependent identity this.delete(depEntity, checkUser, privileges, recursiveDelete, internalModification); } } else { StringBuffer dependentNames = new StringBuffer(); for (IsbEntityBean depEntity : dependents) { // This ISB entity exists on the ISB target // Add the name/identifier to dependent Names & Ids if (dependentNames.length() > 0) { dependentNames.append(", "); } dataLogger.debug("Dependency: " + depEntity.getName()); dependentNames.append(depEntity.getName()); // Throw an exception with their names throw new WhichDoctorDaoException( "Cannot delete this" + " entity, it is required by: " + dependentNames.toString()); } } } boolean success = update(entity, false, false, internalModification); if (success) { // Post a 'delete' message on the ISB for the identified object this.isbTransactionDAO.deleteInstance(entity.getGUID(), entity.getObjectType(), entity.getTarget()); // If the entry was deleted and there are no more occurances of this entity // on any ISB then remove it from the groups. try { final Collection<IsbEntityBean> entities = loadAll(entity.getGUID()); boolean deleteGroupMembership = true; if (entities != null && entities.size() > 0) { deleteGroupMembership = false; } if (deleteGroupMembership) { checkMandatoryGroups(entity.getGUID(), true, privileges); } } catch (WhichDoctorDaoException wde) { dataLogger.error("Error deleting mandatory group items: " + wde.getMessage()); } } return success; } /** * Update the IsbEntityBean. * * @param entity the entity * @param status the status * @param internalCreation the internal creation * @param internalModification the internal modification * * @return true, if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ private boolean update(final IsbEntityBean entity, final boolean status, final boolean internalCreation, final boolean internalModification) throws WhichDoctorDaoException { boolean success = false; // Get the ISB Target Type int isbTypeId = 0; try { ObjectTypeBean object = this.getObjectTypeDAO().load("ISB Target", "", entity.getTarget()); isbTypeId = object.getObjectTypeId(); } catch (Exception e) { throw new WhichDoctorDaoException("Error loading ISB target type: " + e.getMessage()); } // Get the WhichDoctor object Type int objectTypeId = 0; try { ObjectTypeBean object = this.getObjectTypeDAO().load("WhichDoctor", "", entity.getObjectType()); objectTypeId = object.getObjectTypeId(); } catch (Exception e) { throw new WhichDoctorDaoException("Error loading WhichDoctor object type: " + e.getMessage()); } // Set the timestamp values Timestamp creationTimeStamp = null; Timestamp updateTimeStamp = null; Timestamp exportTimeStamp = null; // Set the default values of the timestamps try { creationTimeStamp = new Timestamp(entity.getCreatedDate().getTime()); } catch (Exception e) { dataLogger.debug("Creation timestamp could not be created: " + e.getMessage()); } try { updateTimeStamp = new Timestamp(entity.getModifiedDate().getTime()); } catch (Exception e) { dataLogger.debug("Update timestamp could not be created: " + e.getMessage()); } try { exportTimeStamp = new Timestamp(entity.getExportedDate().getTime()); } catch (Exception e) { dataLogger.debug("Export timestamp could not be created: " + e.getMessage()); } if (internalCreation) { // The record has been created (added) to the ISB try { creationTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); } catch (Exception e) { dataLogger.debug("Creation timestamp could not be created: " + e.getMessage()); } } else { if (internalModification) { try { updateTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); } catch (Exception e) { dataLogger.debug("Update timestamp could not be created: " + e.getMessage()); } } else { try { exportTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); } catch (Exception e) { dataLogger.debug("Export timestamp could not be created: " + e.getMessage()); } } } try { final int updateCount = this.getJdbcTemplateWriter().update(this.getSQL().getValue("isbentity/update"), new Object[] { entity.getGUID(), isbTypeId, objectTypeId, entity.getIdentifier(), entity.getName(), creationTimeStamp, updateTimeStamp, exportTimeStamp, status, entity.getIdentifier(), entity.getName(), creationTimeStamp, updateTimeStamp, exportTimeStamp, status }); if (updateCount > 0) { success = true; } } catch (DataAccessException de) { dataLogger.error("Error updating ISB entity: " + de.getMessage()); } checkRelationships(entity); return success; } /** * Updates the Internal Update timestamp for all active ISB entities with * the specified GUID. * * @param guid the guid * * @throws WhichDoctorDaoException the which doctor dao exception */ public final void update(final int guid) throws WhichDoctorDaoException { final Timestamp sqlTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); try { this.getJdbcTemplateWriter().update(this.getSQL().getValue("isbentity/updateId"), new Object[] { sqlTimeStamp, guid, true }); } catch (DataAccessException de) { dataLogger.error("Error updating ISB entity update time: " + de.getMessage()); } } /** * Updates the Internal Update timestamp for all active ISB entities with * the specified identifier string. * * @param identifier the identifier * * @throws WhichDoctorDaoException the which doctor dao exception */ public final void update(final String identifier) throws WhichDoctorDaoException { final Timestamp sqlTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); try { this.getJdbcTemplateWriter().update(this.getSQL().getValue("isbentity/updateIdentifier"), new Object[] { sqlTimeStamp, identifier, true }); } catch (DataAccessException de) { dataLogger.error("Error updating ISB entity update time: " + de.getMessage()); } } /** * Check that the entities related to the supplied IsbEntity are on the bus * as well. * * @param entity the entity */ private void checkRelationships(final IsbEntityBean entity) { if (StringUtils.equalsIgnoreCase(entity.getObjectType(), "Person")) { /* The IsbEntity is a person load this and their related entities */ BuilderBean loadDetails = new BuilderBean(); loadDetails.setParameter("RELATIONSHIPS", true); PersonBean person = null; try { person = this.personDAO.loadGUID(entity.getGUID(), loadDetails); } catch (Exception e) { dataLogger.error("Error loading person related to IsbEntity: " + e.getMessage()); } if (person != null) { Collection<RelationshipBean> relationships = person.getRelationships(); for (RelationshipBean relationship : relationships) { // Iterate through the relationships array // If the relationship has a mapping check for the entity if (StringUtils.isNotBlank(relationship.getISBMapping())) { IsbEntityBean relatedEntity = null; try { relatedEntity = this.load(entity.getTarget(), relationship.getReferenceGUID()); } catch (Exception e) { dataLogger.error("Error loading ISB entity: " + e.getMessage()); } if (relatedEntity == null) { // This entity does not exist on the target create relatedEntity = new IsbEntityBean(); relatedEntity.setGUID(relationship.getReferenceGUID()); relatedEntity.setIdentifier(relationship.getIdentifier()); relatedEntity.setName(relationship.getName()); relatedEntity.setTarget(entity.getTarget()); relatedEntity.setObjectType("Person"); try { this.create(relatedEntity, false, new UserBean(), new PrivilegesBean(), true); } catch (Exception e) { dataLogger.error("Error creating related " + "ISB entity: " + e.getMessage()); } } } } } } } /** * Load isb entity. * * @param rs the rs * * @return the isb entity bean * * @throws SQLException the SQL exception */ private IsbEntityBean loadIsbEntity(final ResultSet rs) throws SQLException { IsbEntityBean entity = new IsbEntityBean(); entity.setId(rs.getInt("Id")); entity.setGUID(rs.getInt("GUID")); entity.setIdentifier(rs.getString("Identifier")); entity.setName(rs.getString("Name")); entity.setTarget(rs.getString("Target")); entity.setObjectType(rs.getString("ObjectType")); entity.setActive(rs.getBoolean("Active")); try { entity.setCreatedDate(rs.getTimestamp("CreatedInternal")); } catch (SQLException e) { dataLogger.debug("Error reading CreatedInternal date: " + e.getMessage()); } try { entity.setModifiedDate(rs.getTimestamp("ModifiedInternal")); } catch (SQLException e) { dataLogger.debug("Error reading ModifiedInternal date: " + e.getMessage()); } try { entity.setExportedDate(rs.getTimestamp("ModifiedExternal")); } catch (SQLException e) { dataLogger.debug("Error reading ModifiedExternal date: " + e.getMessage()); } return entity; } /** * Check mandatory group membership. * * @param entityGUID the entity guid * @param delete the entity reference if present (otherwise create if not) * @param privileges the privileges */ private void checkMandatoryGroups(final int entityGUID, final boolean delete, final PrivilegesBean privileges) { if (this.mandatoryGroups != null) { UserBean systemUser = getSystemUser("ISB", "System"); dataLogger.debug("Mandatory groups exist"); for (Integer groupGUID : this.mandatoryGroups.keySet()) { TreeMap<String, ItemBean> items = new TreeMap<String, ItemBean>(); String isbMapping = ""; try { final GroupBean group = this.groupDAO.loadGUID(groupGUID); isbMapping = group.getGroupDN(); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error loading the parent group: " + wde.getMessage()); } try { items = this.itemDAO.load(groupGUID, false, "Group", "Member", entityGUID, null, null); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error performing search for items: " + wde.getMessage()); } if (items != null && items.size() == 0 && !delete) { dataLogger.debug("Items do not exist and create selected"); // No items exist and create is requested. final ItemBean item = new ItemBean(); item.setObject1GUID(groupGUID); item.setObject2GUID(entityGUID); item.setWeighting(WEIGHTING); item.setPermission(PERMISSION); item.setItemType(ITEMTYPE); try { this.itemDAO.create(item, systemUser, privileges, isbMapping); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error creating the new item: " + wde.getMessage()); } } if (items != null && items.size() > 0 && delete) { // Items exist and delete is requested. dataLogger.debug("Items exist and delete selected"); for (String key : items.keySet()) { final ItemBean item = items.get(key); try { this.itemDAO.delete(item, systemUser, privileges, isbMapping); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error deleting the existing item: " + wde.getMessage()); } } } } } } }