Java tutorial
/******************************************************************************* * Copyright (c) 2012 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.webservice; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; 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.jdom.Document; import org.jdom.Element; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import com.sfs.Formatter; import com.sfs.beans.BuilderBean; import com.sfs.whichdoctor.beans.AccreditationBean; import com.sfs.whichdoctor.beans.AssessmentBean; import com.sfs.whichdoctor.beans.OrganisationBean; import com.sfs.whichdoctor.beans.PersonBean; import com.sfs.whichdoctor.beans.ProjectBean; import com.sfs.whichdoctor.beans.RelationshipBean; import com.sfs.whichdoctor.beans.ReportBean; import com.sfs.whichdoctor.beans.RotationBean; import com.sfs.whichdoctor.beans.SpecialtyBean; import com.sfs.whichdoctor.dao.OrganisationDAO; import com.sfs.whichdoctor.dao.RelationshipDAO; import com.sfs.whichdoctor.dao.WhichDoctorDaoException; import com.sfs.whichdoctor.webservice.helper.RotationXmlHelper; import com.sfs.whichdoctor.webservice.helper.ToolCount; import com.sfs.whichdoctor.webservice.helper.ToolCounts; import com.sfs.whichdoctor.webservice.helper.TrainingRequirement; /** * The Class RotationXmlOutputImpl. */ public class RotationXmlOutputImpl implements RotationXmlOutput { /** The logger. */ private static Logger logger = Logger.getLogger(RotationXmlOutputImpl.class); /** The Constant PERCENTAGE_MULTIPLIER. */ private static final int PERCENTAGE_MULTIPLIER = 100; /** The Constant WORKING_DAYS. */ private static final double WORKING_DAYS = 5; /** The organisation dao. */ @Resource private OrganisationDAO organisationDAO; /** The relationship dao. */ @Resource private RelationshipDAO relationshipDAO; /** The relationship mapping. */ private Map<String, String> relationshipMapping = new TreeMap<String, String>(); /** * Sets the relationship mapping. * This is of the form WhichDoctor relationship type -> Web Service type. * e.g. Education -> edu * * @param relationshipMap the relationship map */ public final void setRelationshipMapping(final Map<String, String> relationshipMap) { this.relationshipMapping = relationshipMap; } /** * Builds a list of rotations in the first-gen XML format. * * @param rotations the rotation array * @param personIdentifier the person identifier * @param division the division * * @return the rotations in the legacy XML format */ public final String getFirstGenRotations(final List<RotationBean> rotations, final int personIdentifier, final String division) { int totalApprovedCore = 0; int totalApprovedNonCore = 0; int totalCertifiedCore = 0; int totalCertifiedNonCore = 0; int totalEligibleUnits = 0; int rotationCount = 0; double trainingTime = 0; Collection<RotationBean> basicRotations = new ArrayList<RotationBean>(); Collection<Element> rtnsXml = new ArrayList<Element>(); // Only the basic training rotations are required for legacy output for (RotationBean rtn : rotations) { if (StringUtils.equalsIgnoreCase(rtn.getRotationType(), "Basic Training")) { basicRotations.add(rtn); } } for (RotationBean rtn : basicRotations) { int approvedCore = 0; int approvedNonCore = 0; int certifiedCore = 0; int certifiedNonCore = 0; int eligibleUnits = (int) Formatter.round((rtn.getTotalDays() / WORKING_DAYS), 0); totalEligibleUnits += eligibleUnits; if (rtn.getAccreditation() != null) { for (AccreditationBean acn : rtn.getAccreditation()) { if (acn.getCore()) { approvedCore += acn.getWeeksApproved(); certifiedCore += acn.getWeeksCertified(); } else { approvedNonCore += acn.getWeeksApproved(); certifiedNonCore += acn.getWeeksCertified(); } } } rotationCount++; totalApprovedCore += approvedCore; totalApprovedNonCore += approvedNonCore; totalCertifiedCore += certifiedCore; totalCertifiedNonCore += certifiedNonCore; Calendar startDate = Calendar.getInstance(); Calendar endDate = Calendar.getInstance(); if (rtn.getStartDate() != null) { startDate.setTime(rtn.getStartDate()); } if (rtn.getEndDate() != null) { endDate.setTime(rtn.getEndDate()); } // Add to the total training time trainingTime += rtn.getTrainingTime(); Map<Integer, RelationshipBean> supervisors = this.relationshipDAO.getSupervisorMap(rtn); rtnsXml.add(RotationXmlHelper.getFirstGenRotationInfo(rtn, division, startDate, endDate, approvedCore, approvedNonCore, certifiedCore, certifiedNonCore, eligibleUnits, supervisors, this.relationshipMapping)); } if (rotationCount > 0) { trainingTime = Formatter.round(trainingTime / rotationCount * PERCENTAGE_MULTIPLIER, 2); } Element xml = new Element("rotations"); xml.setAttribute("min", String.valueOf(personIdentifier)); xml.addContent(new Element("timeperc").setText(String.valueOf(trainingTime))); String partfull = "Part-time"; if (trainingTime >= PERCENTAGE_MULTIPLIER) { partfull = "Full-time"; } xml.addContent(new Element("partfull").setText(partfull)); xml.addContent(new Element("totalcoreunits").setText(String.valueOf(totalApprovedCore))); xml.addContent(new Element("totalnoncoreunits").setText(String.valueOf(totalApprovedNonCore))); xml.addContent(new Element("totalaccredcoreunits").setText(String.valueOf(totalCertifiedCore))); xml.addContent(new Element("totalaccrednoncoreunits").setText(String.valueOf(totalCertifiedNonCore))); xml.addContent(new Element("totaleligunits").setText(String.valueOf(totalEligibleUnits))); xml.addContent(new Element("unitmeasure").setText("weeks")); xml.addContent(rtnsXml); XMLOutputter outputter = new XMLOutputter(); Format format = Format.getCompactFormat(); format.setOmitDeclaration(true); outputter.setFormat(format); return outputter.outputString(new Document(xml)); } /** * Builds a list of rotations in the second-gen XML format. * * @param rotations the rotation array * @param personIdentifier the person identifier * @param division the division * @param currentRotations the current rotations * * @return the rotations in XML format */ public final String getSecondGenRotations(final List<RotationBean> rotations, final int personIdentifier, final String division, final Collection<RotationBean> currentRotations) { Element xml = new Element("trainee"); xml.setAttribute("MIN", String.valueOf(personIdentifier)); // Process the current organisations TreeMap<String, Element> siteMap = new TreeMap<String, Element>(); for (RotationBean rtn : currentRotations) { if (StringUtils.isNotBlank(rtn.getOrganisation1Name())) { Element site = new Element("site"); String type = "primary"; if (!StringUtils.equalsIgnoreCase(type, rtn.getOrganisation1TypeMapping())) { // If not primary set the type to training type = "training"; } site.setAttribute("type", "current_" + type); site.setAttribute("state", loadOrgCity(rtn.getOrganisation1Id())); site.setAttribute("name", rtn.getOrganisation1Name()); siteMap.put(type, site); } if (StringUtils.isNotBlank(rtn.getOrganisation2Name())) { Element site = new Element("site"); String type = "training"; if (siteMap.containsKey(type)) { // Set to primary if the training key exists type = "primary"; } site.setAttribute("type", "current_" + type); site.setAttribute("state", loadOrgCity(rtn.getOrganisation2Id())); site.setAttribute("name", rtn.getOrganisation2Name()); siteMap.put(type, site); } } if (siteMap.size() == 1) { for (String type : siteMap.keySet()) { Element site = siteMap.get(type); Element site2 = (Element) site.clone(); String secondType = "training"; if (StringUtils.equalsIgnoreCase(type, "training")) { secondType = "primary"; } site2.setAttribute("type", "current_" + secondType); siteMap.put(secondType, site2); } } Element sitesElement = new Element("sites"); for (String type : siteMap.keySet()) { Element site = siteMap.get(type); sitesElement.addContent(site); } xml.addContent(sitesElement); Element rtnsXml = new Element("rotations"); rtnsXml.setAttribute("min", String.valueOf(personIdentifier)); for (RotationBean rtn : rotations) { rtnsXml.addContent(RotationXmlHelper.getSecondGenRotationInfo(rtn, division, loadOrgCity(rtn.getOrganisation1Id()), loadOrgCity(rtn.getOrganisation2Id()))); } xml.addContent(rtnsXml); XMLOutputter outputter = new XMLOutputter(); Format format = Format.getCompactFormat(); format.setOmitDeclaration(true); outputter.setFormat(format); return outputter.outputString(new Document(xml)); } /** * Builds a list of rotations in the third-gen (PE1) XML format. * * @param rotations the rotation array * @param personIdentifier the person identifier * @param division the division * @param trainingType the training type * @return the rotations in XML format */ public final String getThirdGenRotations(final List<RotationBean> rotations, final int personIdentifier, final String division, final String trainingType) { List<RotationBean> selectedRotations = new ArrayList<RotationBean>(); if (rotations != null) { for (RotationBean rotation : rotations) { if (StringUtils.equalsIgnoreCase(trainingType, "BT")) { // Only include basic training rotations if (StringUtils.equalsIgnoreCase(rotation.getRotationType(), "Basic Training")) { selectedRotations.add(rotation); } } else { // Exclude basic training rotations if (!StringUtils.equalsIgnoreCase(rotation.getRotationType(), "Basic Training")) { selectedRotations.add(rotation); } } } } Element tnXml = new Element("Trainee"); tnXml.setAttribute("min", String.valueOf(personIdentifier)); Element rtnsXml = new Element("Rotations"); for (RotationBean rtn : selectedRotations) { if (rtn.getAssessment() != null && rtn.getAssessment().size() > 0) { Map<Integer, Collection<AccreditationBean>> accreditationMap = getAccreditationMap(rtn); int i = 0; for (AssessmentBean assessment : rtn.getAssessment()) { rtnsXml.addContent(RotationXmlHelper.getThirdGenRotationInfo(rtn, assessment, accreditationMap.get(i), division, loadOrgCity(rtn.getOrganisation1Id()), loadOrgCity(rtn.getOrganisation2Id()))); i++; } } else { rtnsXml.addContent(RotationXmlHelper.getThirdGenRotationInfo(rtn, new AssessmentBean(), new ArrayList<AccreditationBean>(), division, loadOrgCity(rtn.getOrganisation1Id()), loadOrgCity(rtn.getOrganisation2Id()))); } } tnXml.addContent(rtnsXml); XMLOutputter outputter = new XMLOutputter(); Format format = Format.getCompactFormat(); format.setOmitDeclaration(true); outputter.setFormat(format); return outputter.outputString(new Document(tnXml)); } /** * Builds the XML output for the training tool count. * * @param person the person * @param trainingType the training type * @return the tool count */ public final String getToolCount(final PersonBean person, final String trainingType) { Map<String, ToolCounts> toolCounts = new TreeMap<String, ToolCounts>(Collections.reverseOrder()); if (person != null) { if (person.getProjects() != null) { for (ProjectBean project : person.getProjects()) { ToolCount tool = getToolCount(project, trainingType); if (tool != null) { ToolCounts tc = new ToolCounts(); tc.setMeasure("program"); if (project.getYear() > 0) { tc.setMeasure("year"); tc.setYear(project.getYear()); } if (toolCounts.containsKey(tc.getOrderKey())) { tc = toolCounts.get(tc.getOrderKey()); } tc.addManualToolCount(tool); toolCounts.put(tc.getOrderKey(), tc); } } } if (person.getRotations() != null) { for (RotationBean rotation : person.getRotations()) { List<ToolCount> tools = getToolCounts(rotation, trainingType); for (ToolCount tool : tools) { // Need to check whether a manual or report ToolCounts tc = new ToolCounts(); tc.setMeasure("year"); tc.setYear(rotation.getYear()); if (toolCounts.containsKey(tc.getOrderKey())) { tc = toolCounts.get(tc.getOrderKey()); } if (tool.isManualToolCount()) { tc.addManualToolCount(tool); } else { tc.addReportToolCount(tool); } toolCounts.put(tc.getOrderKey(), tc); } } } } Element xml = new Element("ToolCountsInfo"); for (String key : toolCounts.keySet()) { ToolCounts tcs = toolCounts.get(key); Element tcsXml = new Element("ToolCounts"); String measure = "program"; String year = ""; if (!StringUtils.equalsIgnoreCase(tcs.getMeasure(), "program")) { measure = "year"; if (tcs.getYear() > 0) { year = String.valueOf(tcs.getYear()); } } tcsXml.setAttribute("measure", measure); tcsXml.setAttribute("year", year); if (tcs.getManualToolCounts().size() > 0) { tcsXml.addContent(getToolCountXml("manual", tcs.getManualToolCounts())); } if (tcs.getReportToolCounts().size() > 0) { tcsXml.addContent(getToolCountXml("report", tcs.getReportToolCounts())); } xml.addContent(tcsXml); } XMLOutputter outputter = new XMLOutputter(); Format format = Format.getCompactFormat(); format.setOmitDeclaration(true); outputter.setFormat(format); return outputter.outputString(new Document(xml)); } /** * Gets the XML output for the training requirement years. * * @param person the person * @param trainingType the training type * @return the training requirement years */ public final String getTrainingRequirementYears(final PersonBean person, final String trainingType) { Map<String, TrainingRequirement> requirements = new TreeMap<String, TrainingRequirement>(); if (person != null) { if (person.getSpecialtyList() != null) { for (SpecialtyBean sp : person.getSpecialtyList()) { TrainingRequirement requirement = getTrainingRequirement(person, sp, trainingType); if (requirement != null) { String key = "D:" + requirement.getDivision() + "-S:" + requirement.getTrainingProgram(); if (!requirements.containsKey(key)) { requirements.put(key, requirement); } } } } // Iterate through the rotations to see what years are applicable // for the identified specialties. if (person.getRotations() != null) { for (String key : requirements.keySet()) { TrainingRequirement requirement = requirements.get(key); for (RotationBean rotation : person.getRotations()) { int year = getTrainingRequirementYear(requirement, rotation); requirement.addYearToList(year); } } } } Element xml = new Element("Trainings"); xml.setAttribute("type", trainingType); for (String key : requirements.keySet()) { TrainingRequirement requirement = requirements.get(key); Element req = new Element("RequirementYears"); req.setAttribute("division", requirement.getDivision()); req.setAttribute("country", requirement.getCountryAbbreviation()); req.setAttribute("STP", requirement.getTrainingProgramShortName()); String curriculumYear = ""; if (requirement.getYear() > 0) { curriculumYear = String.valueOf(requirement.getYear()); } req.setAttribute("curriculumYear", curriculumYear); for (Integer year : requirement.getYearList()) { if (year > 0) { Element yr = new Element("Year").addContent(String.valueOf(year)); req.addContent(yr); } } xml.addContent(req); } XMLOutputter outputter = new XMLOutputter(); Format format = Format.getCompactFormat(); format.setOmitDeclaration(true); outputter.setFormat(format); return outputter.outputString(new Document(xml)); } /** * Gets the training requirement. Returns null if not applicable. * * @param person the person * @param specialty the specialty * @param trainingType the training type * @return the training requirement */ private TrainingRequirement getTrainingRequirement(final PersonBean person, final SpecialtyBean specialty, final String trainingType) { TrainingRequirement requirement = null; boolean includeSpecialty = false; String division = "", country = "", isbRole = ""; if (StringUtils.equalsIgnoreCase(trainingType, "BT")) { // Basic training requirements if (StringUtils.equalsIgnoreCase(specialty.getTrainingProgram(), "Basic Training")) { division = "A"; country = "NZ"; includeSpecialty = true; if (StringUtils.equalsIgnoreCase(specialty.getTrainingOrganisation(), "RACP - Paediatric")) { division = "P"; } if (StringUtils.equalsIgnoreCase(person.getMembershipField("Status"), "Active - within Australia")) { country = "AU"; } } } else { // Assume AT/Post-FRACP requirements if (!StringUtils.equalsIgnoreCase(specialty.getTrainingProgram(), "Basic Training")) { includeSpecialty = true; isbRole = specialty.getIsbRole(2); } } if (includeSpecialty) { requirement = new TrainingRequirement(); requirement.setDivision(division); requirement.setTrainingType(trainingType); requirement.setTrainingOrganisation(specialty.getTrainingOrganisation()); requirement.setTrainingProgram(specialty.getTrainingProgram()); requirement.setTrainingProgramISBMapping(isbRole); requirement.setYear(specialty.getTrainingProgramYear()); requirement.setCountryAbbreviation(country); } return requirement; } /** * Gets the training requirement year. * * @param requirement the requirement * @param rotation the rotation * @return the training requirement year */ private int getTrainingRequirementYear(final TrainingRequirement requirement, final RotationBean rotation) { int year = 0; if (rotation.getAssessment() != null) { for (AssessmentBean assessment : rotation.getAssessment()) { if (StringUtils.equalsIgnoreCase(requirement.getTrainingOrganisation(), assessment.getTrainingOrganisation()) && StringUtils.equalsIgnoreCase(requirement.getTrainingProgram(), assessment.getTrainingProgram())) { // Organisation and training programs match - set year. year = rotation.getYear(); } } } return year; } /** * Gets the tool count. Returns null if not valid for the training type. * * @param project the project * @param trainingType the training type * @return the tool count */ private ToolCount getToolCount(final ProjectBean project, final String trainingType) { ToolCount tool = null; if (!StringUtils.equalsIgnoreCase(trainingType, "BT")) { tool = new ToolCount(); tool.setManualToolCount(true); tool.setName(project.getAssessmentType()); tool.setSubName(project.getProjectType()); tool.setTrainingType(trainingType); tool.setTrainingProgramISBMapping(project.getTrainingProgramISBMapping()); } return tool; } /** * Gets the tool counts for a rotation. * * @param rt the rt * @param trainingType the training type * @return the tool counts */ private List<ToolCount> getToolCounts(final RotationBean rt, final String trainingType) { List<ToolCount> tools = new ArrayList<ToolCount>(); Map<String, ToolCount> toolHits = new TreeMap<String, ToolCount>(); boolean processReports = false; if (rt != null) { if (StringUtils.equalsIgnoreCase(rt.getRotationType(), "Basic Training") && StringUtils.equalsIgnoreCase(trainingType, "BT")) { // This is a basic training rotation and BT has been requested processReports = true; } if (!StringUtils.equalsIgnoreCase(rt.getRotationType(), "Basic Training") && !StringUtils.equalsIgnoreCase(trainingType, "BT")) { // This is not a basic training rotation an BT has not been requested processReports = true; } } if (processReports && rt.getReports() != null) { for (ReportBean report : rt.getReports()) { if (report.getReportPublish()) { ToolCount tc = new ToolCount(); tc.setName(report.getReportType()); if (StringUtils.equalsIgnoreCase(report.getReportGrouping(), "Manual")) { tc.setManualToolCount(true); } String key = report.getReportOrder() + "_" + report.getReportType(); toolHits.put(key, tc); } } } for (String key : toolHits.keySet()) { ToolCount tc = toolHits.get(key); tools.add(tc); } return tools; } /** * Gets the accreditation map. * * @param rotation the rotation * @return the accreditation map */ private Map<Integer, Collection<AccreditationBean>> getAccreditationMap(final RotationBean rotation) { Map<Integer, Collection<AccreditationBean>> accreditationMap = new HashMap<Integer, Collection<AccreditationBean>>(); if (rotation != null && rotation.getAccreditation() != null) { if (rotation.getAssessment().size() > 1) { Map<String, Collection<AccreditationBean>> accreditedSpecialties = new HashMap<String, Collection<AccreditationBean>>(); for (AccreditationBean accreditation : rotation.getAccreditation()) { String key = accreditation.getSpecialtyType(); Collection<AccreditationBean> accreditations = new ArrayList<AccreditationBean>(); if (accreditedSpecialties.containsKey(key)) { accreditations = accreditedSpecialties.get(key); } accreditations.add(accreditation); accreditedSpecialties.put(key, accreditations); } int i = 0; for (AssessmentBean asmt : rotation.getAssessment()) { String key = asmt.getCommitteeSpecialty(); Collection<AccreditationBean> accreditations = new ArrayList<AccreditationBean>(); if (accreditedSpecialties.containsKey(key)) { accreditations = accreditedSpecialties.get(key); } accreditationMap.put(i, accreditations); accreditedSpecialties.remove(key); i++; } // Any accreditation left in the map is added to the first assessment Collection<AccreditationBean> firstAccreds = accreditationMap.get(0); for (String key : accreditedSpecialties.keySet()) { Collection<AccreditationBean> accred = accreditedSpecialties.get(key); for (AccreditationBean accreditation : accred) { firstAccreds.add(accreditation); } } accreditationMap.put(0, firstAccreds); } else { accreditationMap.put(0, rotation.getAccreditation()); } } return accreditationMap; } /** * Gets the tool count xml. * * @param type the type * @param toolCounts the tool counts * @return the tool count xml */ private Element getToolCountXml(final String type, final TreeMap<String, ToolCount> toolCounts) { Element tctXml = new Element("ToolCountType"); tctXml.setAttribute("name", type); for (String id : toolCounts.keySet()) { ToolCount tc = toolCounts.get(id); Element tcXml = new Element("ToolCount"); tcXml.setAttribute("name", tc.getName()); tcXml.setAttribute("subName", tc.getSubName()); tcXml.setAttribute("STP", tc.getTrainingProgramShortName()); tcXml.addContent(String.valueOf(tc.getCount())); tctXml.addContent(tcXml); } return tctXml; } /** * Load the city associated with the organisation. * * @param organisationGUID the organisation guid * @return the string */ private String loadOrgCity(final int organisationGUID) { String city = ""; if (organisationGUID > 0) { // Load the organisation in order to get its city try { BuilderBean loadDetails = new BuilderBean(); loadDetails.setParameter("ADDRESS", true); OrganisationBean org = this.organisationDAO.loadGUID(organisationGUID, loadDetails); if (org.getFirstAddress() != null) { city = org.getFirstAddress().getCity(); } } catch (WhichDoctorDaoException wde) { logger.error("Error loading organisation: " + wde.getMessage()); } } return city; } }