| summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/Group.java')
| -rw-r--r-- | src/Group.java | 560 |
1 files changed, 560 insertions, 0 deletions
diff --git a/src/Group.java b/src/Group.java new file mode 100644 index 0000000..3e1a1f2 --- /dev/null +++ b/src/Group.java @@ -0,0 +1,560 @@ +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; + +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.FileWriter; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.IOException; + +import java.net.URL; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +public class Group extends Thread +{ + private static final HashMap<String, Group> KNOWN_GROUPS; + private final HashMap<String, PrintWriter> class_files; + private final String name; + private final String abbreviation; + private final String[] url; + private final Group.Type[] type; + + static + { + KNOWN_GROUPS = new HashMap<String, Group>(); + } + + private Group + ( + final String name, + final String abbreviation, + final String[] types_and_urls + ) + { + final int sources; + int j; + + sources = (types_and_urls.length / 2); + + this.name = name; + this.abbreviation = abbreviation; + + url = new String[sources]; + type = new Group.Type[sources]; + + for (int i = 0; i < sources; ++i) + { + j = (i * 2); + type[i] = Type.get(types_and_urls[j]); + url[i] = types_and_urls[j + 1]; + } + + class_files = new HashMap<String, PrintWriter>(); + } + + private void register () + throws Group.AlreadyRegisteredException + { + if (KNOWN_GROUPS.containsKey(abbreviation)) + { + throw (new Group.AlreadyRegisteredException()); + } + + KNOWN_GROUPS.put(abbreviation, this); + } + + public String get_abbreviation () + { + return abbreviation; + } + + public void add_event (final Event event) + { + final PrintWriter pw; + + pw = + class_files.get + ( + Classes.abbreviation_from_name + ( + event.get_name(), + false + ) + ); + + pw.println(event.toString()); + pw.flush(); + } + + public void add_ICS_fragment + ( + final String fragment, + final String class_name, + final boolean lazy + ) + { + final PrintWriter pw; + + pw = + class_files.get + ( + Classes.abbreviation_from_name(class_name, lazy) + ); + + // Escapes all ',' or ';' not directly preceded by '\'. + // That's quite an inefficient way to do it btw. + pw.print + ( + fragment.replaceAll + ( + "(?<!\\\\),", + "\\\\," + ).replaceAll + ( + "(?<!\\\\);", + "\\\\;" + ) + ); + + pw.flush(); + } + + private static enum Type + { + CELCAT(true), + DHX_CAL(true), + ICS(false), + LAZY_ICS(false), + ICS_NOUID(false), + LAZY_ICS_NOUID(false), + CAMSI(false); + + public final boolean uses_xml; + + private Type (final boolean uses_xml) + { + this.uses_xml = uses_xml; + } + + public static Type get (final String str) + { + if (str.equals("celcat")) + { + return CELCAT; + } + else if (str.equals("dhx_cal")) + { + return DHX_CAL; + } + else if (str.equals("ics_nouid")) + { + return ICS_NOUID; + } + else if (str.equals("lazy_ics_nouid")) + { + return LAZY_ICS_NOUID; + } + else if (str.equals("ics")) + { + return ICS; + } + else if (str.equals("lazy_ics")) + { + return LAZY_ICS; + } + else if (str.equals("camsi")) + { + return CAMSI; + } + + return null; + } + } + + private boolean create_class_files () + { + try + { + for (final String abbr: Classes.get_all_abbreviations()) + { + class_files.put + ( + abbr, + new PrintWriter + ( + new FileWriter + ( + Parameters.get_output_directory() + + "/" + + abbreviation + + "_" + + abbr + + ".ics" + ) + ) + ); + } + + class_files.put + ( + "unknown", + new PrintWriter + ( + new FileWriter + ( + Parameters.get_output_directory() + + "/" + + abbreviation + + "_unknown.ics" + ) + ) + ); + } + catch (final IOException e) + { + Error.ERROR.from_thread + ( + abbreviation, + ("Could not create output file: " + e.toString()) + ); + + return false; + } + + return true; + } + + private void finalize_class_files () + { + for (final PrintWriter pw: class_files.values()) + { + pw.flush(); + pw.close(); + } + } + + private InputStreamReader remove_fuckups + ( + final InputStreamReader irs + ) + throws Exception + { + final BufferedReader in; + final PrintWriter pw; + final String filename; + String input; + boolean first_line; + + filename = + ( + Parameters.get_output_directory() + + "/" + + abbreviation + + ".fuckup" + ); + + in = new BufferedReader(irs); + pw = new PrintWriter(filename); + + first_line = true; + + while ((input = in.readLine()) != null) + { + if (!input.equals("")) + { + if (first_line) + { + pw.println(input.trim().replaceFirst("^([\\W]+)<","<")); + first_line = false; + } + else + { + pw.println(input); + } + } + } + + pw.close(); + irs.close(); + + return (new InputStreamReader(new FileInputStream(filename))); + } + + private void parse_source + ( + final int id, + final Group.Type type, + final String url + ) + throws Exception + { + final XMLInputFactory input_factory; + final XMLStreamReader stream_reader; + final StringBuilder sb; + + if (type.uses_xml) + { + input_factory = XMLInputFactory.newInstance(); + stream_reader = + input_factory.createXMLStreamReader + ( + remove_fuckups(new InputStreamReader((new URL(url)).openStream(), "UTF-8")) + ); + sb = new StringBuilder(); + + sb.append(abbreviation); + sb.append("_s"); + sb.append(id); + sb.append("_event"); + } + else + { + stream_reader = null; + sb = null; + } + + switch (type) + { + case CELCAT: + CelcatParser.parse(stream_reader, this, sb.toString()); + break; + + case DHX_CAL: + DHXCalParser.parse(stream_reader, this, sb.toString()); + break; + + case ICS_NOUID: + ICSParser.parse(url, this, false, true); + break; + + case LAZY_ICS_NOUID: + ICSParser.parse(url, this, true, true); + break; + + case ICS: + ICSParser.parse(url, this, false, false); + break; + + case LAZY_ICS: + ICSParser.parse(url, this, true, false); + break; + + case CAMSI: + CAMSIParser.parse + ( + new BufferedReader + ( + new InputStreamReader + ( + (new URL(url)).openStream() + ) + ), + this, + (abbreviation + "_s" + id + "_event") + ); + break; + } + } + + @Override + public void run () + { + + if (!create_class_files()) + { + return; + } + + for (int i = 0; i < type.length; ++i) + { + try + { + parse_source(i, type[i], url[i]); + } + catch (final Exception e) + { + final StringBuilder sb; + + sb = new StringBuilder(); + + sb.append("An error occured while parsing source '"); + sb.append(url[i]); + sb.append("'"); + + Error.ERROR.from_thread + ( + abbreviation, + sb.toString(), + e.getMessage() + ); + } + } + + finalize_class_files(); + } + + public static void read_all () + { + BufferedReader br; + String input_line; + String[] data; + Group new_group; + + br = null; + + try + { + br = + new BufferedReader + ( + new InputStreamReader + ( + new FileInputStream(Parameters.get_groups_filename()) + ) + ); + + while ((input_line = br.readLine()) != null) + { + data = input_line.split("::"); + + if (data.length >= 4 && ((data.length % 2) == 0)) + { + new_group = + new Group + ( + data[0], + data[1], + Arrays.copyOfRange(data, 2, data.length) + ); + + try + { + new_group.register(); + } + catch (final Group.AlreadyRegisteredException e) + { + final StringBuilder sb; + + sb = new StringBuilder(); + + sb.append("Duplicate group entry for group \""); + sb.append(new_group.name); + sb.append("\"."); + + Error.ERROR.from_file + ( + Parameters.get_groups_filename(), + sb.toString() + ); + + continue; + } + } + else + { + final StringBuilder sb; + + sb = new StringBuilder(); + + sb.append("Invalid group entry: \""); + sb.append(input_line); + sb.append("\"."); + + Error.ERROR.from_file + ( + Parameters.get_groups_filename(), + sb.toString() + ); + + continue; + } + } + } + catch (final Exception e) + { + Error.FATAL.from_file + ( + Parameters.get_groups_filename(), + "Error while reading file:", + e.getMessage() + ); + + if (br != null) + { + try + { + br.close(); + } + catch (final Exception e2) + { + Error.WARNING.from_file + ( + Parameters.get_groups_filename(), + "Error while closing file:", + e2.getMessage() + ); + } + } + + return; + } + + try + { + br.close(); + } + catch (final Exception e) + { + Error.WARNING.from_file + ( + Parameters.get_groups_filename(), + "Error while closing file:", + e.getMessage() + ); + } + } + + /** + * Creates Group threads (one per group) to translate each XML file. + * For performance reasons, we limit the number of threads running + * concurrently at a give time (also, I'm on shared hosting and the task + * doesn't actually need to be very fast so I avoid being too greedy). + **/ + public static void run_all () + { + final ExecutorService exec; + final List<Callable<Object>> groups; + + groups = new ArrayList<Callable<Object>>(); + + exec = Executors.newFixedThreadPool(Parameters.get_max_threads()); + + for (final Group g: KNOWN_GROUPS.values()) + { + groups.add(Executors.callable(g)); + } + + /** This won't return until all is done. **/ + try + { + exec.invokeAll(groups); + } + catch (final InterruptedException ie) + { + Error.FATAL.from_thread("main", "Interrupted before the end."); + } + + exec.shutdown(); + } + + private static class AlreadyRegisteredException extends Exception {} +} |


