import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Calendar;
import java.util.Locale;
import java.util.Iterator;
import java.util.TimeZone;
import java.io.PrintWriter;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamException;
/**
* This class stores the incoming data from XML.
* It is needed because of the stream nature of the XML parser.
**/
public class DHXCalParser
{
private final Group group;
private String uid_prefix;
private Event event;
private DataType data_type;
private int event_count;
public static void parse
(
final XMLStreamReader stream_reader,
final Group group,
final String uid_prefix
)
throws XMLStreamException
{
final DHXCalParser parser;
parser = new DHXCalParser(group, uid_prefix);
while (stream_reader.hasNext())
{
switch (stream_reader.next())
{
case XMLStreamReader.START_ELEMENT:
parser.handle_new_element(stream_reader);
break;
case XMLStreamReader.CDATA:
case XMLStreamReader.CHARACTERS:
parser.handle_data(stream_reader.getText().trim());
break;
case XMLStreamReader.END_DOCUMENT:
parser.flush();
break;
default:
break;
}
}
}
private DHXCalParser
(
final Group group,
final String uid_prefix
)
{
this.group = group;
this.uid_prefix = uid_prefix;
event = null;
event_count = 0;
}
/**
* Called when entering an new element.
**/
private void handle_new_element (final XMLStreamReader stream_reader)
{
final DataType new_data_type;
new_data_type = DataType.get(stream_reader.getLocalName());
switch (new_data_type)
{
case EVENT:
/** We're done handling the previous event. **/
flush();
break;
default:
break;
}
data_type = new_data_type;
}
private void flush ()
{
if (event == null)
{
/**
* This is the first event, we don't have anything to write.
**/
event = new Event();
event.set_uid(uid_prefix + (event_count++));
return;
}
group.add_event(event);
event = new Event();
event.set_uid(uid_prefix + (event_count++));
}
/**
* Called when finding actual data.
**/
private void handle_data (final String data)
{
final String[] info;
final StringBuilder sb;
int i;
if (data.equals(""))
{
/**
* Data was garbage.
* It happens sometimes, I don't know why.
**/
/* [XXX][Improvement] Prevent this from happening. */
return;
}
/**
* Uses the previously set "data_type" to know where the data belongs.
**/
switch (data_type)
{
case START_DATE:
event.set_start_time(date_to_calendar(data));
break;
case END_DATE:
event.set_end_time(date_to_calendar(data));
break;
case TEXT:
info =
data.replaceAll
(
"|",
""
).replaceAll
(
"\\s+",
" "
).split("
");
event.set_name(info[0]);
sb = new StringBuilder();
for (i = 1; i < info.length; ++i)
{
sb.append(info[i].trim());
sb.append(", ");
}
if (info.length > 1)
{
sb.delete((sb.length() - 2), sb.length());
}
event.set_description(sb.toString());
break;
case DETAILS:
// TODO
break;
default:
break;
}
}
private static Calendar date_to_calendar (final String data)
{
final String[] day_hour;
final String[] hour;
final String[] day;
final java.util.Calendar result;
day_hour = data.split(" ");
hour = day_hour[1].split(":");
day = day_hour[0].split("-");
result =
java.util.Calendar.getInstance
(
TimeZone.getTimeZone("Europe/Paris"),
Locale.FRENCH
);
result.set(java.util.Calendar.DAY_OF_MONTH, Integer.parseInt(day[2]));
/* Java... don't ask... */
result.set(java.util.Calendar.MONTH, Integer.parseInt(day[1]) - 1);
result.set(java.util.Calendar.YEAR, Integer.parseInt(day[0]));
result.set(java.util.Calendar.HOUR_OF_DAY, Integer.parseInt(hour[0]));
result.set(java.util.Calendar.MINUTE, Integer.parseInt(hour[1]));
return result;
}
/**
* This enum is used to sort what is relevant in the XML file.
* Sadly, for justified reasons, Java does not permit access to the static
* members of an enum from its constructor, hence the "static"'s redundancy.
**/
private static enum DataType
{
IRRELEVANT,
EVENT,
START_DATE,
END_DATE,
TEXT,
DETAILS,
DATA;
private static final HashMap FROM_STRING;
static
{
FROM_STRING = new HashMap();
FROM_STRING.put("irrelevant", IRRELEVANT);
FROM_STRING.put("event", EVENT);
FROM_STRING.put("start_date", START_DATE);
FROM_STRING.put("end_date", END_DATE);
FROM_STRING.put("text", TEXT);
FROM_STRING.put("details", DETAILS);
FROM_STRING.put("data", DATA);
}
public static DataType get (final String e)
{
final DataType result;
result = FROM_STRING.get(e);
if (result == null)
{
return IRRELEVANT;
}
return result;
}
}
}