package application.parsing; import java.text.ParseException; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import application.enums.BiologicalSex; import application.enums.BloodType; import application.enums.EntryType; import application.enums.SkinType; import application.helpers.Utils; import application.res.Text; /** * This class is in charge of reading in the data of the file and getting an overview of the data. * @author Bianca * */ public class ReadHandler extends DefaultHandler { /** The date the health data was exported**/ private String exportDate; /** the biological sex given in the health data **/ private BiologicalSex bSex; /** the blood type given in the health data **/ private BloodType bloodType; /** the skin type given in the health data **/ private SkinType skinType; /** the region code given in the health data **/ private String regionCode; /** the date of birth as a string given in the health data**/ private String dateOfBirthString; /** the date of birth saved in a calendar**/ private Calendar dateOfBirth; /** contains as a key the name of tags (e.g EntryTypes) and as value the number of occurrences**/ private HashMap names=new HashMap<>(); /** contains as a key the name of the sub workout and as value the number of occurrences **/ private HashMap subWorkouts=new HashMap<>(); /** contains as a key the name of the sub records and as value the number of occurrences **/ private HashMap subRecords=new HashMap<>(); /** keeps track of the tag layer. With every new element we increase the layer by one**/ private int overallLayer=0; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //increase layer if(overallLayer>0) { overallLayer++; } if (qName.equalsIgnoreCase(Text.TAG_NAME_HEALTH_DATA)) { //outermost tag (overallLayer==0) overallLayer++; regionCode=attributes.getValue(Text.TAG_ATTR_REGION_CODE); } else if (qName.equalsIgnoreCase(EntryType.EXPORT_DATE.getValue())) { exportDate=attributes.getValue(Text.TAG_ATTR_EXPORT_DATE); } else if (qName.equalsIgnoreCase(Text.TAG_NAME_ME_INFO)) { bSex = BiologicalSex.getValue(attributes.getValue(Text.TAG_ATTR_BIOLOGICAL_SEX)); dateOfBirthString = attributes.getValue(Text.TAG_ATTR_DATE_OF_BIRTH); bloodType = BloodType.getValue(attributes.getValue(Text.TAG_ATTR_BLOOD_TYPE)); skinType = SkinType.getValue(attributes.getValue(Text.TAG_ATTR_SKIN_TYPE)); if(dateOfBirthString!=null&&!dateOfBirthString.equals("")) { try { dateOfBirth=new GregorianCalendar(); dateOfBirth.setTime(Utils.formatDateOfBirth.parse(dateOfBirthString)); } catch (ParseException e) { dateOfBirth=null; //do nth if parsing error } } } else if (qName.equalsIgnoreCase(EntryType.RECORD.getValue())) { String subRecord=attributes.getValue(Text.TAG_ATTR_RECORD_TYPE); Integer j = subRecords.get(subRecord); if (j == null) { j = 0; } subRecords.put(subRecord, ++j); } else if (qName.equalsIgnoreCase(EntryType.WORKOUT.getValue())) { String subWorkout=attributes.getValue(Text.TAG_ATTR_WORKOUT_TYPE); Integer j = subWorkouts.get(subWorkout); if (j == null) { j = 0; } subWorkouts.put(subWorkout, ++j); } if(overallLayer==2) //layer 2 means direct descendants of the document root (HealthData-tag) { Integer v=names.get(qName); if (v==null) { v=0; } names.put(qName, ++v); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //decrease layer if(overallLayer>0) { overallLayer--; } } /** * Returns the selected value from ME or ExportDate. * * @param type Value to find the info for. * @return Found value if it was a valid entry of ME or the export Date, * {@code null} otherwise */ public String getMeInfo(EntryType type) { if (type.equals(EntryType.BIOLOGICAL_SEX)) { return bSex.getReadableValue(); } else if (type.equals(EntryType.DATE_OF_BIRTH)) { return getDateOfBirth(); } if (type.equals(EntryType.BLOOD_TYPE)) { return bloodType.getReadableValue(); } if (type.equals(EntryType.SKIN_TYPE)) { return skinType.getReadableValue(); } return null; } /** * Returns the day the health data was exported * @return the described value. */ public String getExportDate() { return exportDate; } /** * Returns the region code given in the file. * @return the described value. */ public String getRegionCode() { return regionCode; } /** * Finds out how many Entries of the given EntryTypes can be found in the * document * * @param type EntryType to find the count to * @return 0 if there are none, otherwise the correct number of entries */ public int getTypeNumber(EntryType type) { if (names.get(type.getValue()) == null) { return 0; } return names.get(type.getValue()); } /** * Returns the year of birth if the data was given in the file. Otherwise returns -1. * @return the described value. */ public int getDateOfBirthYear() { if(dateOfBirth!=null) { return dateOfBirth.get(Calendar.YEAR); } return -1; } /** * Returns the month of birth if the data was given in the file. Otherwise returns -1. * @return the described value. */ public int getDateOfBirthMonth() { if(dateOfBirth!=null) { return dateOfBirth.get(Calendar.MONTH)+1; } return -1; } /** * Returns the day of birth if the data was given in the file. Otherwise returns -1. * @return the described value. */ public int getDateOfBirthDay() { if(dateOfBirth!=null) { return dateOfBirth.get(Calendar.DAY_OF_MONTH); } return -1; } /** * Returns the SubWorkouts with their respective occurrences * @return The described value */ public HashMap getSubWorkouts() { return subWorkouts; } /** * Returns the SubRecords with their respective occurrences * @return The described value */ public HashMap getSubRecords() { return subRecords; } /** * Returns the date of birth as the String read in the file * @return The described value. */ public String getDateOfBirth() { return dateOfBirthString; } /** * Returns the date of birth split into 3 parts (day, month, year) * @return the described value */ public HashMap getSplitDateOfBirth() { HashMap res= new HashMap<>(); if(getDateOfBirthDay()>0) { res.put(Text.DAY, getDateOfBirthDay()); } if(getDateOfBirthMonth()>0) { res.put(Text.MONTH, getDateOfBirthMonth()); } if(getDateOfBirthYear()>0) { res.put(Text.YEAR, getDateOfBirthYear()); } return res; } /** * Returns the biological sex as given in the file * @return the described value */ public BiologicalSex getBSex() { return bSex; } }