diff --git a/appointment-import/.classpath b/appointment-import/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..f7b62f180179a74fbb8400870e0e56b071065daa --- /dev/null +++ b/appointment-import/.classpath @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" output="target/classes" path="src/main/java"> + <attributes> + <attribute name="optional" value="true"/> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="src" output="target/test-classes" path="src/test/java"> + <attributes> + <attribute name="optional" value="true"/> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="output" path="target/classes"/> +</classpath> diff --git a/appointment-import/.gitignore b/appointment-import/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d --- /dev/null +++ b/appointment-import/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/appointment-import/.project b/appointment-import/.project new file mode 100644 index 0000000000000000000000000000000000000000..eee5e1c7df61a5e6865e9a8584bb8c4c4becfe6a --- /dev/null +++ b/appointment-import/.project @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>appointment-import</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.m2e.core.maven2Builder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.m2e.core.maven2Nature</nature> + </natures> +</projectDescription> diff --git a/appointment-import/.settings/org.eclipse.core.resources.prefs b/appointment-import/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000000000000000000000000000000000..04cfa2c1a8566d64dd12fcf7a8e895fe02e1856f --- /dev/null +++ b/appointment-import/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/<project>=UTF-8 diff --git a/appointment-import/.settings/org.eclipse.jdt.core.prefs b/appointment-import/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..bbcbc93486d53c73668b275ea5daf41b66ba9c41 --- /dev/null +++ b/appointment-import/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/appointment-import/.settings/org.eclipse.m2e.core.prefs b/appointment-import/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..14b697b7bbb0d85e8d8ee19141a2a92d9ce211be --- /dev/null +++ b/appointment-import/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/appointment-import/pom.xml b/appointment-import/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..d1022957a5e69e7f4f44fd69f5d63c9751999fcf --- /dev/null +++ b/appointment-import/pom.xml @@ -0,0 +1,67 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>smash</groupId> + <artifactId>appointment-import</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>jar</packaging> + + <name>appointment-import</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> +<dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.17</version> +</dependency> +<dependency> + <groupId>org.apache.poi</groupId> + <artifactId>poi-ooxml</artifactId> + <version>3.15</version> +</dependency> + </dependencies> + + <build> + <plugins> +<plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.5.1</version> + <configuration> + <source>1.7</source> + <target>1.7</target> + </configuration> +</plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <source>1.7</source> + <target>1.7</target> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <mainClass>smash.appointment.parse.Main</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/appointment-import/src/main/java/smash/appointment/parse/AppointmentEntry.java b/appointment-import/src/main/java/smash/appointment/parse/AppointmentEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..8db01548e360c728d0b554e32b4c23eb29ad4203 --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/AppointmentEntry.java @@ -0,0 +1,99 @@ +package smash.appointment.parse; + +public class AppointmentEntry { + private String day; + private String time; + private Subject subject; + private AppointmentType type; + private String source; + + /** + * @return the time + * @see #time + */ + public String getTime() { + return time; + } + + /** + * @param time + * the time to set + * @see #time + */ + public void setTime(String time) { + this.time = time; + } + + /** + * @return the subject + * @see #subject + */ + public Subject getSubject() { + return subject; + } + + /** + * @param subject + * the subject to set + * @see #subject + */ + public void setSubject(Subject subject) { + this.subject = subject; + } + + /** + * @return the type + * @see #type + */ + public AppointmentType getType() { + return type; + } + + /** + * @param type + * the type to set + * @see #type + */ + public void setType(AppointmentType type) { + this.type = type; + } + + /** + * @return the day + * @see #day + */ + public String getDay() { + return day; + } + + /** + * @param day + * the day to set + * @see #day + */ + public void setDay(String day) { + this.day = day; + } + + /** + * @return the source + * @see #source + */ + public String getSource() { + return source; + } + + /** + * @param source + * the source to set + * @see #source + */ + public void setSource(String source) { + this.source = source; + } + + @Override + public String toString() { + return day + " " + time + " " + subject + " " + type + "\t\t[source: " + source + "]"; + } +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/AppointmentType.java b/appointment-import/src/main/java/smash/appointment/parse/AppointmentType.java new file mode 100644 index 0000000000000000000000000000000000000000..bb60199f8bc60e7e03a4b872dc016388e9ef70d3 --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/AppointmentType.java @@ -0,0 +1,34 @@ +package smash.appointment.parse; + +public enum AppointmentType { + + //most complex should be first + LEVEL_BV_BG_SB(new String[] { "evel BV + BG + SB","BV + BG + SB" }), // + LEVEL_BV_SB(new String[] { "evel BV + SB","BV + SB" }), // + LEVEL_BV_BG(new String[] { "evel BV + BG","BV + BG" }), // + LEVEL_BG_SB(new String[] { "evel BG + SB","BG + SB" }), // + LEVEL_BV(new String[] { "evel BV", "BV" }), // + LEVEL_BG(new String[] { "evel BG","BG" }), // + LEVEL_SB(new String[] { "evel SB", "SB" }), // + + LEVEL_A(new String[] { "level A" }), // + OTHER(new String[] {}), // + LEVEL_B(new String[] { "evel B" }), // + LEVEL_B_M_POWER(new String[] { "mPower" }), // + ; + + private String[] queryStrings; + + private AppointmentType(String[] queryStrings) { + this.queryStrings = queryStrings; + + } + + /** + * @return the queryStrings + * @see #queryStrings + */ + public String[] getQueryStrings() { + return queryStrings; + } +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/CellParser.java b/appointment-import/src/main/java/smash/appointment/parse/CellParser.java new file mode 100644 index 0000000000000000000000000000000000000000..efc2e38837080ba883a10342b79f2092d8bae27d --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/CellParser.java @@ -0,0 +1,158 @@ +package smash.appointment.parse; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +public class CellParser { + Logger logger = Logger.getLogger(CellParser.class); + + private SubjectDao subjectDao; + + Pattern timePattern = Pattern.compile("^[0-9][0-9]\\:[0-9][0-9]"); + + public String extractTime(String content) { + String result = null; + Matcher matcher = timePattern.matcher(content); + if (matcher.find()) { + result = matcher.group(); + } + return result; + } + + public String removeTime(String content) { + Matcher matcher = timePattern.matcher(content); + if (matcher.find()) { + content = matcher.replaceFirst("").trim(); + } + return content; + } + + public AppointmentEntry parseAppointment(String query, String defaultTime) { + AppointmentEntry result = new AppointmentEntry(); + + String time = extractTime(query); + if (time != null) { + query = removeTime(query); + } else { + time = defaultTime; + } + result.setTime(time); + + Subject subject = extractSubject(query); + result.setSubject(subject); + + AppointmentType type = extractType(query); + if (type == null) { + type = AppointmentType.OTHER; + } + result.setType(type); + + result.setSource(query); + return result; + } + + private AppointmentType extractType(String query) { + String simplifiedQuery = Utils.simplifyString(query); + + AppointmentType result = null; + + String usedString = null; + for (AppointmentType type : AppointmentType.values()) { + boolean matchFound = false; + for (String string : type.getQueryStrings()) { + if (!matchFound) { + String simplifiedString = Utils.simplifyString(string); + + if (simplifiedQuery.contains(simplifiedString)) { + matchFound = true; + if (result == null) { + result = type; + usedString = string; + } else { + if (string.contains(usedString)) { + result = type; + usedString = string; + } else if (usedString.contains(string)) { + //new one is a substring of old + } else { //if there is no substring then we might have a problem + AppointmentType newType = result; + if (usedString.length() < string.length()) { + result = type; + usedString = string; + } + logger.warn("More than one type possible for query: " + query + ". Type 1: " + result + ". Type 2: " + type + ". Choosing: " + newType); + } + } + + } + } + } + } + return result; + } + + private Subject extractSubject(String query) { + Subject result = null; + String simplifiedQuery = Utils.simplifyString(query); + + SubjectIndexer[] mainIndices = new SubjectIndexer[] { // + new NameSurnameIndexer(), // + new SurnameNameIndexer(), // + new NdNumberIndexer(),// + }; + + result = getByIndices(query, simplifiedQuery, mainIndices); + if (result == null) { + SubjectIndexer[] secondaryIndices = new SubjectIndexer[] { // + new SurnameIndexer(), // + }; + result = getByIndices(query, simplifiedQuery, secondaryIndices); + } + return result; + } + + private Subject getByIndices(String query, String simplifiedQuery, SubjectIndexer[] mainIndices) { + Subject result = null; + for (Subject subject : subjectDao.getSubjects()) { + boolean matchFound = false; + for (SubjectIndexer indexer : mainIndices) { + if (!matchFound) { + if (indexer.match(subject, simplifiedQuery)) { + matchFound = true; + if (result == null) { + result = subject; + } else { + Subject newResult = result; + if (indexer.isBetter(subject, result)) { + newResult = subject; + } + logger.warn( + "More than one subject possible for query: " + query + ". Subject 1: " + result + ". Subject 2: " + subject + ". Choosing: " + newResult); + result = newResult; + } + } + } + } + } + return result; + } + + /** + * @return the subjectDao + * @see #subjectDao + */ + public SubjectDao getSubjectDao() { + return subjectDao; + } + + /** + * @param subjectDao + * the subjectDao to set + * @see #subjectDao + */ + public void setSubjectDao(SubjectDao subjectDao) { + this.subjectDao = subjectDao; + } +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/Main.java b/appointment-import/src/main/java/smash/appointment/parse/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..051de5b0c3a5f0019c10fa02654ccf525a684f75 --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/Main.java @@ -0,0 +1,27 @@ +package smash.appointment.parse; + +import java.util.List; + +import org.apache.log4j.Logger; + +public class Main { + private static Logger logger = Logger.getLogger(Main.class); + + public static void main(String[] args) throws Exception { + if (args.length < 2) { + System.out.println("Usage: command <agenda.xlsx> <subjects.txt>"); + } else { + SubjectDao subjectDao = new SubjectDao(); + subjectDao.readFile(args[1]); + + XlsxCalendarProcessor processor = new XlsxCalendarProcessor(); + processor.setSubjectDao(subjectDao); + + List<AppointmentEntry> entries = processor.processExcel(args[0]); + for (AppointmentEntry appointmentEntry : entries) { + logger.debug(appointmentEntry); + } + } + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/NameSurnameIndexer.java b/appointment-import/src/main/java/smash/appointment/parse/NameSurnameIndexer.java new file mode 100644 index 0000000000000000000000000000000000000000..2ed820ad2e1b4609692d2eaf7233254a6784c0fc --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/NameSurnameIndexer.java @@ -0,0 +1,9 @@ +package smash.appointment.parse; + +public class NameSurnameIndexer extends SubjectIndexer { + + public String getIndexedString(Subject subject) { + return Utils.simplifyString(subject.getName() + subject.getSurname()); + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/NdNumberIndexer.java b/appointment-import/src/main/java/smash/appointment/parse/NdNumberIndexer.java new file mode 100644 index 0000000000000000000000000000000000000000..cd96a4a1a0149f439d7436689350279fe87d92fb --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/NdNumberIndexer.java @@ -0,0 +1,9 @@ +package smash.appointment.parse; + +public class NdNumberIndexer extends SubjectIndexer { + + public String getIndexedString(Subject subject) { + return Utils.simplifyString(subject.getNdNumber()); + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/Subject.java b/appointment-import/src/main/java/smash/appointment/parse/Subject.java new file mode 100644 index 0000000000000000000000000000000000000000..ee5cc02d6c6d686db57fa55826d001e0326c2526 --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/Subject.java @@ -0,0 +1,89 @@ +package smash.appointment.parse; + +public class Subject { + private String name; + private String surname; + private String ndNumber; + private String screeningNumber; + + public Subject(String name, String surname, String ndNumber, String screeningNumber) { + this.name = name; + this.surname = surname; + this.ndNumber = ndNumber; + this.screeningNumber = screeningNumber; + } + + /** + * @return the name + * @see #name + */ + public String getName() { + return name; + } + + /** + * @param name + * the name to set + * @see #name + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the surname + * @see #surname + */ + public String getSurname() { + return surname; + } + + /** + * @param surname + * the surname to set + * @see #surname + */ + public void setSurname(String surname) { + this.surname = surname; + } + + /** + * @return the ndNumber + * @see #ndNumber + */ + public String getNdNumber() { + return ndNumber; + } + + /** + * @param ndNumber + * the ndNumber to set + * @see #ndNumber + */ + public void setNdNumber(String ndNumber) { + this.ndNumber = ndNumber; + } + + /** + * @return the screeningNumber + * @see #screeningNumber + */ + public String getScreeningNumber() { + return screeningNumber; + } + + /** + * @param screeningNumber + * the screeningNumber to set + * @see #screeningNumber + */ + public void setScreeningNumber(String screeningNumber) { + this.screeningNumber = screeningNumber; + } + + @Override + public String toString() { + return this.getName() + " " + this.getSurname() + " (" + this.getNdNumber() + "; " + this.getScreeningNumber() + ")"; + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/SubjectDao.java b/appointment-import/src/main/java/smash/appointment/parse/SubjectDao.java new file mode 100644 index 0000000000000000000000000000000000000000..c852c84c6242cc2004c0af2184a8db68e4bb74bc --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/SubjectDao.java @@ -0,0 +1,43 @@ +package smash.appointment.parse; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class SubjectDao { + private List<Subject> subjects = new ArrayList<Subject>(); + + public void addSubject(Subject subject) { + subjects.add(subject); + } + + public void readFile(String filename) throws IOException { + try (BufferedReader br = new BufferedReader(new FileReader(filename))) { + String line; + while ((line = br.readLine()) != null) { + String tmp[] = line.split("\t"); + addSubject(new Subject(tmp[0], tmp[1], tmp[2], tmp[3])); + } + } + } + + /** + * @return the subjects + * @see #subjects + */ + public List<Subject> getSubjects() { + return subjects; + } + + /** + * @param subjects + * the subjects to set + * @see #subjects + */ + public void setSubjects(List<Subject> subjects) { + this.subjects = subjects; + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/SubjectIndexer.java b/appointment-import/src/main/java/smash/appointment/parse/SubjectIndexer.java new file mode 100644 index 0000000000000000000000000000000000000000..ff89c24faad3525f473abdc8d8ca9c1fdaf4ab10 --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/SubjectIndexer.java @@ -0,0 +1,22 @@ +package smash.appointment.parse; + +import org.apache.log4j.Logger; + +public abstract class SubjectIndexer { + Logger logger = Logger.getLogger(SubjectIndexer.class); + + public abstract String getIndexedString(Subject subject); + + public boolean match(Subject subject, String simplifiedQuery) { + String indexedString = getIndexedString(subject); +// logger.debug("Check: " + simplifiedQuery + " against: " + indexedString); + if (simplifiedQuery.startsWith(indexedString)) { + return true; + } + return false; + } + + public boolean isBetter(Subject subject, Subject oldSubject) { + return getIndexedString(subject).length()>getIndexedString(oldSubject).length(); + } +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/SurnameIndexer.java b/appointment-import/src/main/java/smash/appointment/parse/SurnameIndexer.java new file mode 100644 index 0000000000000000000000000000000000000000..10c1a29f3e39236ed33c0c819e6a30d4420de99c --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/SurnameIndexer.java @@ -0,0 +1,9 @@ +package smash.appointment.parse; + +public class SurnameIndexer extends SubjectIndexer { + + public String getIndexedString(Subject subject) { + return Utils.simplifyString(subject.getSurname()); + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/SurnameNameIndexer.java b/appointment-import/src/main/java/smash/appointment/parse/SurnameNameIndexer.java new file mode 100644 index 0000000000000000000000000000000000000000..7de6d7c4ef96e23ee9b75a72fa5d32eb1f6b5ad1 --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/SurnameNameIndexer.java @@ -0,0 +1,9 @@ +package smash.appointment.parse; + +public class SurnameNameIndexer extends SubjectIndexer { + + public String getIndexedString(Subject subject) { + return Utils.simplifyString(subject.getSurname() + subject.getName()); + } + +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/Utils.java b/appointment-import/src/main/java/smash/appointment/parse/Utils.java new file mode 100644 index 0000000000000000000000000000000000000000..0667ea3eb5cdc466b5a573e75f12ae3f546b89df --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/Utils.java @@ -0,0 +1,7 @@ +package smash.appointment.parse; + +public class Utils { + public static String simplifyString(String query) { + return query.replaceAll("[\\s\\-©]", "").toLowerCase(); + } +} diff --git a/appointment-import/src/main/java/smash/appointment/parse/XlsxCalendarProcessor.java b/appointment-import/src/main/java/smash/appointment/parse/XlsxCalendarProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..9066b95799bd7bfded806ef23b8ad07b2300f59a --- /dev/null +++ b/appointment-import/src/main/java/smash/appointment/parse/XlsxCalendarProcessor.java @@ -0,0 +1,142 @@ +package smash.appointment.parse; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; + +public class XlsxCalendarProcessor { + Logger logger = Logger.getLogger(XlsxCalendarProcessor.class); + + private SubjectDao subjectDao; + + public List<AppointmentEntry> processExcel(String filename) throws EncryptedDocumentException, InvalidFormatException, IOException, ParseException { + List<AppointmentEntry> result = new ArrayList<AppointmentEntry>(); + InputStream inp = new FileInputStream(filename); + Workbook workbook = WorkbookFactory.create(inp); + Iterator<Sheet> sheetIter = workbook.sheetIterator(); + while (sheetIter.hasNext()) { + Sheet sheet = sheetIter.next(); + String name = sheet.getSheetName().trim(); + if (name.contains("2017")) { + String monthName = name.split(" ")[0]; + String monthNumber = parseMonth(monthName); + result.addAll(processSheet(sheet, "2017-" + monthNumber)); + } else { + logger.debug("Skipping sheet: " + name); + } + } + return result; + } + + int[] dayColumns = new int[] { 3, 4, 5, 6, 7 }; + + int[] weekStartRows = new int[] { 5, 23, 41, 60, 78, 96 }; + + int hourColum = 0; + int dayOfMonthRowOffset = 0; + int calendarRowStartOffset = 3; + int calendarRowEndOffset = 18; + + private List<AppointmentEntry> processSheet(Sheet sheet, String string) { + List<AppointmentEntry> result = new ArrayList<AppointmentEntry>(); + + CellParser parser = new CellParser(); + parser.setSubjectDao(subjectDao); + + for (int weekOffset : weekStartRows) { + Row weekRow = sheet.getRow(weekOffset + dayOfMonthRowOffset); + for (int dayColumnOffset : dayColumns) { + Cell dayCell = weekRow.getCell(dayColumnOffset); + String dayOfMonth = ((int) dayCell.getNumericCellValue()) + ""; + if (dayOfMonth.length() == 1) { + dayOfMonth = "0" + dayOfMonth; + } + if (!dayOfMonth.equals("00")) { + String day = string + "-" + dayOfMonth; + + String hour = "08:00"; + for (int hourOffset = calendarRowStartOffset; hourOffset < calendarRowEndOffset; hourOffset++) { + Row hourRow = sheet.getRow(weekOffset + hourOffset); + + Cell hourCell = hourRow.getCell(hourColum); + if (hourCell.getCellTypeEnum().equals(CellType.NUMERIC)) { + + SimpleDateFormat formatTime = new SimpleDateFormat("HH:mm"); + String hourString = formatTime.format(hourCell.getDateCellValue()); + + if (isHour(hourString)) { + hour = hourString; + } + } + + String query = hourRow.getCell(dayColumnOffset).getStringCellValue(); + + if (query != null && !query.isEmpty()) { + AppointmentEntry entry = parser.parseAppointment(query, hour); + entry.setDay(day); + + result.add(entry); + } + } + } + } + + } + return result; + } + + Pattern timePattern = Pattern.compile("^[0-9][0-9]\\:[0-9][0-9]"); + + private boolean isHour(String hourString) { + Matcher matcher = timePattern.matcher(hourString); + return matcher.find(); + } + + private String parseMonth(String monthName) throws ParseException { + Date date = new SimpleDateFormat("MMMM", Locale.ENGLISH).parse(monthName); + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + String result = (cal.get(Calendar.MONTH) + 1) + ""; + if (result.length() == 1) { + result = "0" + result; + } + return result; + } + + /** + * @return the subjectDao + * @see #subjectDao + */ + public SubjectDao getSubjectDao() { + return subjectDao; + } + + /** + * @param subjectDao + * the subjectDao to set + * @see #subjectDao + */ + public void setSubjectDao(SubjectDao subjectDao) { + this.subjectDao = subjectDao; + } +} diff --git a/appointment-import/src/main/resources/log4j.properties b/appointment-import/src/main/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..e108a78cf8570a6f5bfc3e00dfaee3c45a1e829e --- /dev/null +++ b/appointment-import/src/main/resources/log4j.properties @@ -0,0 +1,8 @@ +#Set root logger 's level and its appender to an appender called CONSOLE which is defined below. +log4j.rootLogger=debug, CONSOLE + +#Set the behavior of the CONSOLE appender +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n +#log4j.appender.CONSOLE.layout.ConversionPattern=%m%n diff --git a/appointment-import/src/test/java/smash/appointment/parse/AllTests.java b/appointment-import/src/test/java/smash/appointment/parse/AllTests.java new file mode 100644 index 0000000000000000000000000000000000000000..80dc2e923c352fd7f99c0a18378f0ac8cec14ba2 --- /dev/null +++ b/appointment-import/src/test/java/smash/appointment/parse/AllTests.java @@ -0,0 +1,14 @@ +package smash.appointment.parse; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ CellParserTest.class, // + SubjectDaoTest.class, // + XlsxCalendarProcessorTest.class, // +}) +public class AllTests { + +} diff --git a/appointment-import/src/test/java/smash/appointment/parse/CellParseTestCase.java b/appointment-import/src/test/java/smash/appointment/parse/CellParseTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..5bc5156649eb06657b40d4b7f4210e7ea593c924 --- /dev/null +++ b/appointment-import/src/test/java/smash/appointment/parse/CellParseTestCase.java @@ -0,0 +1,15 @@ +package smash.appointment.parse; + +class CellParseTestCase { + String query; + Subject subject; + String time; + AppointmentType type; + + public CellParseTestCase(String query, Subject subject, String time, AppointmentType type) { + this.query = query; + this.subject = subject; + this.time = time; + this.type = type; + } +}; diff --git a/appointment-import/src/test/java/smash/appointment/parse/CellParserTest.java b/appointment-import/src/test/java/smash/appointment/parse/CellParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..40311eba2e5bb3b9e53956fb2903a3960908b4ce --- /dev/null +++ b/appointment-import/src/test/java/smash/appointment/parse/CellParserTest.java @@ -0,0 +1,77 @@ +package smash.appointment.parse; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class CellParserTest extends TestBase { + List<CellParseTestCase> testCases; + CellParser parser; + + @Before + public void setUp() { + super.setUp(); + + parser = new CellParser(); + parser.setSubjectDao(subjectDao); + + testCases = new ArrayList<CellParseTestCase>(); + + testCases.add(new CellParseTestCase("Piotr Gawron level A FU V3", piotrGawron, null, AppointmentType.LEVEL_A)); + testCases.add(new CellParseTestCase("09:00 Jan Kowalski-Nowak level A", janKowalskiNowak, "09:00", AppointmentType.LEVEL_A)); + testCases.add(new CellParseTestCase("ND0002 l664574645 (sms)evel BV © + SB ©", janKowalskiNowak, null, AppointmentType.LEVEL_BV_SB)); + testCases.add(new CellParseTestCase("ND0001 654654631 level B ©", piotrGawron, null, AppointmentType.LEVEL_B)); + testCases.add(new CellParseTestCase("John Doe BV + BG + SB", johnDoe, null, AppointmentType.LEVEL_BV_BG_SB)); + testCases.add(new CellParseTestCase("Kowalski-Nowak m-Power", janKowalskiNowak, null, AppointmentType.LEVEL_B_M_POWER)); + testCases.add(new CellParseTestCase("ND0004 Name BV ©", cateKowalsky, null, AppointmentType.LEVEL_BV)); + + } + + + @Test + public void testExtractTime() { + for (CellParseTestCase testCase : testCases) { + String result = parser.extractTime(testCase.query); + assertEquals("Invalid time parsed from query: " + testCase.query, testCase.time, result); + } + } + + @Test + public void testRemoveTime() { + for (CellParseTestCase testCase : testCases) { + String result = parser.removeTime(testCase.query); + if (testCase.time == null) { + assertEquals("query after removing time should be the same for query: " + testCase.query, testCase.query, result); + } else { + assertFalse(testCase.query.equals(result)); + } + } + } + + @Test + public void testRemoveTime2() { + String result = parser.removeTime("09:00 John Doe level B"); + assertEquals("John Doe level B", result); + } + + @Test + public void testExtractAppointment() { + String defaultTime = "23:55"; + for (CellParseTestCase testCase : testCases) { + AppointmentEntry appointment = parser.parseAppointment(testCase.query, defaultTime); + if (testCase.time != null) { + assertEquals("Invalid time parsed from query: " + testCase.query, testCase.time, appointment.getTime()); + } else { + assertEquals("Invalid time parsed from query (default value expected): " + testCase.query, defaultTime, appointment.getTime()); + } + assertEquals("Invalid subject parsed from query: " + testCase.query, testCase.subject, appointment.getSubject()); + assertEquals("Invalid type parsed from query: " + testCase.query, testCase.type, appointment.getType()); + } + } + +} diff --git a/appointment-import/src/test/java/smash/appointment/parse/SubjectDaoTest.java b/appointment-import/src/test/java/smash/appointment/parse/SubjectDaoTest.java new file mode 100644 index 0000000000000000000000000000000000000000..66fc18c54fc04749163cbd38d5a4cbc0c29a5e9f --- /dev/null +++ b/appointment-import/src/test/java/smash/appointment/parse/SubjectDaoTest.java @@ -0,0 +1,32 @@ +package smash.appointment.parse; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +public class SubjectDaoTest { + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testReadFile() throws Exception { + SubjectDao subjectDao = new SubjectDao(); + subjectDao.readFile("testFiles/subjects.txt"); + assertEquals(2, subjectDao.getSubjects().size()); + assertEquals("Piotr", subjectDao.getSubjects().get(0).getName()); + } + +} diff --git a/appointment-import/src/test/java/smash/appointment/parse/TestBase.java b/appointment-import/src/test/java/smash/appointment/parse/TestBase.java new file mode 100644 index 0000000000000000000000000000000000000000..e3b909e929095ed6ebd890a29195e0f03625364d --- /dev/null +++ b/appointment-import/src/test/java/smash/appointment/parse/TestBase.java @@ -0,0 +1,26 @@ +package smash.appointment.parse; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; + +public class TestBase { + SubjectDao subjectDao; + + Subject piotrGawron = new Subject("Piotr", "Gawron", "ND0001", "1"); + Subject janKowalskiNowak = new Subject("Jan", "Kowalski-Nowak", "ND0002", "2"); + Subject johnDoe = new Subject("John", "Doe", "ND0003", "3"); + Subject cateKowalsky = new Subject("Cate", "Kowalsky", "ND0004", "4"); + + public void setUp() { + subjectDao = new SubjectDao(); + + subjectDao.addSubject(piotrGawron); + subjectDao.addSubject(janKowalskiNowak); + subjectDao.addSubject(johnDoe); + subjectDao.addSubject(cateKowalsky); + } + + +} diff --git a/appointment-import/src/test/java/smash/appointment/parse/XlsxCalendarProcessorTest.java b/appointment-import/src/test/java/smash/appointment/parse/XlsxCalendarProcessorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8c07b60137cb34d5f039f4cf99411dfdc3a80456 --- /dev/null +++ b/appointment-import/src/test/java/smash/appointment/parse/XlsxCalendarProcessorTest.java @@ -0,0 +1,42 @@ +package smash.appointment.parse; + +import static org.junit.Assert.assertTrue; + +import java.io.FileNotFoundException; +import java.util.List; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +public class XlsxCalendarProcessorTest extends TestBase{ + Logger logger = Logger.getLogger(XlsxCalendarProcessorTest .class); + + XlsxCalendarProcessor processor = new XlsxCalendarProcessor(); + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() { + super.setUp(); + processor.setSubjectDao(subjectDao); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testReadExcel() throws Exception { + List<AppointmentEntry> entries = processor.processExcel("testFiles/calendarExample.xlsx"); + assertTrue(entries.size() > 0); +// for (AppointmentEntry appointmentEntry : entries) { +// logger.debug(appointmentEntry); +// } + } + +} diff --git a/appointment-import/src/test/resources/log4j.properties b/appointment-import/src/test/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..e108a78cf8570a6f5bfc3e00dfaee3c45a1e829e --- /dev/null +++ b/appointment-import/src/test/resources/log4j.properties @@ -0,0 +1,8 @@ +#Set root logger 's level and its appender to an appender called CONSOLE which is defined below. +log4j.rootLogger=debug, CONSOLE + +#Set the behavior of the CONSOLE appender +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n +#log4j.appender.CONSOLE.layout.ConversionPattern=%m%n diff --git a/appointment-import/testFiles/calendarExample.xlsx b/appointment-import/testFiles/calendarExample.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..516d8e548c74f5a7b2e1050b80918e0acfe80fc8 Binary files /dev/null and b/appointment-import/testFiles/calendarExample.xlsx differ diff --git a/appointment-import/testFiles/subjects.txt b/appointment-import/testFiles/subjects.txt new file mode 100644 index 0000000000000000000000000000000000000000..c55594f7ee41d31b0b81aaf1b38b46eb949d5bb4 --- /dev/null +++ b/appointment-import/testFiles/subjects.txt @@ -0,0 +1,2 @@ +Piotr Gawron ND0001 1 +John Doe ND0002 2