📄 icalparser.java
字号:
package us.k5n.ical;import java.util.Vector;import java.io.BufferedReader;import java.io.IOException;/** * iCal Parser class - * This object is required for most parsing methods and can be thought * of as the main entry point into this package. * It can serve as a DataStore to store events/todos/etc when a custom * DataStore is not needed. * <br/> * Example usage: * <blockquote><pre> * IcalParser parser = new IcalParser (); * File f = new File ( "/tmp/test.ics" ); * try { * BufferedReader r = new BufferedReader ( new FileReader ( f ) ); * parser.parse ( r ); * } catch ( IOException e ) { * // ... report error * } * r.close (); * Vector events = parser.getAllEvents (); * Vector errors = parser.getAllErrors (); * </pre></blockquote> * @version $Id$ * @author Craig Knudsen, craig@k5n.us */public class IcalParser implements Constants{ int parseMethod; // PARSE_STRICT or PARSE_LOOSE Vector errorListeners; Vector errors; Property icalVersion = null; Property prodId = null; Property method = null; Property calscale = null; String language = "EN"; // default language setting Vector dataStores; // DataStore objects in a Vector static final int STATE_NONE = 0; static final int STATE_VCALENDAR = 1; static final int STATE_VEVENT = 2; static final int STATE_VTODO = 3; static final int STATE_VJOURNAL = 4; static final int STATE_VTIMEZONE = 5; static final int STATE_VFREEBUSY = 6; static final int STATE_DONE = 7; /** * Create an IcalParser object. By default, this will also setup * the default DataStore object. * To remove the default DataStore, you can call removeDataStoreAt(0). * @param parseMethod Specifies the parsing method, which should be * either PARSE_STRICT or PARSE_LOOSE. The PARSE_STRICT * method will follow the RFC 2445 specification * strictly and is intended to be used to validate * iCal data. Most clients should specify PARSE_LOOSE * to capture as much of the data as possible. */ public IcalParser ( int parseMethod ) { this ( parseMethod, "EN" ); } /** * Create an IcalParser object. By default, this will also setup * the default DataStore object. * To remove the default DataStore, you can call removeDataStoreAt(0). * @param parseMethod Specifies the parsing method, which should be * either PARSE_STRICT or PARSE_LOOSE. The PARSE_STRICT * method will follow the RFC 2445 specification * strictly and is intended to be used to validate * iCal data. Most clients should specify PARSE_LOOSE * to capture as much of the data as possible. * @param language Default language setting. When parsing objects, * the property that matches this language setting * will take priority. For example, if "EN" is * specified as a parameter here, and an event * in iCal has a summary in "EN" and also in "FR", then * the summary in "EN" will be returned when * the event is queries for a summary. */ public IcalParser ( int parseMethod, String language ) { this.parseMethod = parseMethod; this.language = language; errorListeners = new Vector (); errors = new Vector (); dataStores = new Vector (); // Add the default DataStore dataStores.addElement ( new DefaultDataStore () ); } /** * Get the current setting for parse method (PARSE_STRICT or PARSE_LOOSE) * @return PARSE_STRICT or PARSE_LOOSE */ public int getParseMethod () { return parseMethod; } /** * Add a DataStore. Each DataStore will be called during the parsing * process as each timezone, event, todo, or journal object is * discovered. * @param dataStore The new DataStore to add */ public void addDataStore ( DataStore dataStore ) { dataStores.addElement ( dataStore ); } /** * Return the number of DataStores currently registered. */ public int numDataStores () { return dataStores.size(); } /** * Return the specified DataStore. * @param ind The DataStore index number (0=first) */ public DataStore getDataStoreAt ( int ind ) { return (DataStore) dataStores.elementAt ( ind ); } /** * Remove the specified DataStore. * @param ind the DataStore index number (0=first) * @return true if the DataStore was found and removed */ public boolean removeDataStoreAt ( int ind ) { if ( ind < dataStores.size() ) { dataStores.removeElementAt ( ind ); return true; } // not found return false; } /** * Is the current parse method set to PARSE_STRICT? * @return true if the current parse method is PARSE_STRICT */ public boolean isParseStrict () { return ( parseMethod == PARSE_STRICT ); } /** * Is the current parse method set to PARSE_LOOSE? * @return true if the current parse method is PARSE_LOOSE */ public boolean isParseLoose () { return ( parseMethod == PARSE_LOOSE ); } /** * Set the current parse method * @param parseMethod The new parse method (PARSE_STRICT, PARSE_LOOSE) */ public void setParseMethod ( int parseMethod ) { this.parseMethod = parseMethod; } /** * Add a listener for parse error messages. * @pel The listener for parse errors */ public void addParseErrorListener ( ParseErrorListener pel ) { errorListeners.addElement ( pel ); } /** * Send a parse error message to all parse error listeners * @param msg The error message * @param icalStr The offending line(s) of iCal */ public void reportParseError ( ParseError error ) { errors.addElement ( error ); for ( int i = 0; i < errorListeners.size(); i++ ) { ParseErrorListener pel = (ParseErrorListener) errorListeners.elementAt ( i ); pel.reportParseError ( error ); } } /** * Get a Vector of all errors encountered;. * @return A Vector of ParseError objects */ public Vector getAllErrors () { return errors; } /** * Parse a File. * @param reader The java.io.Reader object to read the * iCal data from. To parse a String object * use java.io.StringReader. * @return true if no parse errors encountered */ public boolean parse ( java.io.Reader reader ) throws IOException { boolean noErrors = true; String line, nextLine; BufferedReader r = new BufferedReader ( reader ); StringBuffer data = new StringBuffer (); int state = STATE_NONE; int ln = 0; // line number int startLineNo = 0; Vector textLines; boolean done = false; // Because iCal allows lines to be "folded" (continued) onto multiple // lines, you need to peek ahead to the next line to know if you have // all the text for what you are trying to parse. // The "line" variable is what is currently being parsed. The "nextLine" // variable contains the next line of text to be processed. // TODO: line numbers in errors may be off for folded lines since the // last line number of the text will be reported. textLines = new Vector (); nextLine = r.readLine (); while ( ! done ) { line = nextLine; ln++; if ( nextLine != null ) { nextLine = r.readLine(); // if nextLine is null, don't set done to true yet since we still // need another iteration through the while loop for the text // to get processed. } // Check to see if next line is a continuation of the current // line. If it is, then append the contents of the next line // onto the current line. if ( nextLine != null && nextLine.length() > 0 && ( nextLine.charAt ( 0 ) == SPACE || nextLine.charAt ( 0 ) == TAB ) ) { // Line folding found. Add to previous line and continue. nextLine = line + CRLF + nextLine; continue; // skip back to start of while loop } data.append ( line ); String lineUp = line.toUpperCase();//System.out.println ( "[DATA:" + state + "]" + line ); switch ( state ) { case STATE_NONE: if ( lineUp.startsWith ( "BEGIN:VCALENDAR" ) ) state = STATE_VCALENDAR; else if ( lineUp.length() == 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -