1111
1212public abstract class AbstractParser
1313{
14- protected enum ParsingErrors
15- {
16- NO_ERROR , END_OF_BLOCK_REACHED , PARSING_ERROR ;
17-
18- private String mTag ;
19- public void setTag (String name ) { this .mTag = name ; }
20- public String getTag () { return this .mTag ; }
21-
22- }
23-
2414 /* Abstract public methods */
25- public abstract boolean moveToNextEntry () throws Exception ;
26- public abstract void moveToEntryAtOffset (long offset ) throws Exception ;
27- public abstract ParsingErrors parseLine (int linei , ParserResult result ) throws Exception ;
2815 public abstract String getParserVersion ();
2916 public abstract String [] getSupportedKindleVersions ();
3017
18+ /* Abstract protected methods */
19+ protected abstract boolean isTerminationLine (String linestr );
20+ protected abstract boolean parseLine (int linei , ParserResult res ) throws Exception ;
21+
3122 /* Protected fields */
3223 protected String mFileName ;
3324 protected RandomAccessFile mFile ;
3425 protected Charset mCharset ;
3526 protected ParserEvents mParserEvents ;
27+ protected boolean mIsInvalidState ; /* On paring error, this is set to true.
28+ False indicates, no error, or file pointer has
29+ moved to the next block after the previous parsing
30+ error.*/
3631
3732 /* Private fields */
3833 private long mLastFilePointer ;
@@ -47,7 +42,11 @@ protected enum ParsingErrors
4742 public void setParserEvents (ParserEvents value ) { this .mParserEvents = value ; }
4843
4944 /* Hook methods */
50- protected void onParsingStart () throws Exception { }
45+ protected void onParsingStart () throws Exception
46+ {
47+ if (this .mIsInvalidState )
48+ throw new ParserException ("Invalid parser state : On an invalid line." );
49+ }
5150
5251 protected void onParsingSuccess (ParserResult result ) throws Exception
5352 {
@@ -58,6 +57,10 @@ protected void onParsingSuccess (ParserResult result) throws Exception
5857 }
5958 protected void onParsingError (String error , ParserResult result ) throws Exception
6059 {
60+ /* Until we move past the current block to the next block, parser remains in invalid
61+ * state. */
62+ mIsInvalidState = true ;
63+
6164 ParserEvents e = this .mParserEvents ;
6265 if (e == null ) return ;
6366
@@ -82,6 +85,42 @@ public AbstractParser (String fileName) throws FileNotFoundException, IOExceptio
8285 this .mLastLineRead = null ;
8386 this .mLastFilePointer = -1 ;
8487 this .mParserEvents = null ;
88+ this .mIsInvalidState = false ;
89+ }
90+
91+ /**
92+ * Moves to the Title of the next block from anywhere in the current block.
93+ * Moves to the start of the next block. This methods, does not actually parse the lines, it
94+ * just looks for the next termination line.
95+ *
96+ * Returns True, of next block was found, otherwise False.
97+ */
98+ public boolean moveToNextEntry () throws Exception
99+ {
100+ String linestr = null ;
101+
102+ while (true )
103+ {
104+ linestr = readLineWithProperEncoding ();
105+ if (linestr == null )
106+ return false ;
107+
108+ if (isTerminationLine (linestr ))
109+ break ;
110+ }
111+
112+ /* Move past any invalid block.*/
113+ mIsInvalidState = false ;
114+ return true ;
115+ }
116+
117+ /**
118+ * Moves the file pointer and assumes the next line read to be Title.
119+ */
120+ public void moveToEntryAtOffset (long offset ) throws Exception
121+ {
122+ mFile .seek (offset );
123+ mIsInvalidState = false ;
85124 }
86125
87126 protected Charset getCharsetFromByteOrderMarkType (ByteOrderMarkTypes type )
@@ -102,7 +141,6 @@ protected Charset getCharsetFromByteOrderMarkType (ByteOrderMarkTypes type)
102141 */
103142 public ParserResult parse () throws Exception
104143 {
105- ParsingErrors parseError = ParsingErrors .NO_ERROR ;
106144 ParserResult result = new ParserResult ();
107145
108146 /* End of file was reached before */
@@ -112,14 +150,17 @@ public ParserResult parse() throws Exception
112150 return null ;
113151 }
114152
115- try {
153+ try
154+ {
116155 onParsingStart ();
117156
118- for (int i = 0 ; parseError == ParsingErrors .NO_ERROR ; i ++)
157+ boolean isTerminationLineReached = false ;
158+ for (int i = 0 ; isTerminationLineReached == false ; i ++)
119159 {
120160 if (Thread .interrupted () == true )
121161 throw new InterruptedException ();
122- parseError = parseLine (i , result );
162+
163+ isTerminationLineReached = parseLine (i , result );
123164 }
124165
125166 } catch (InterruptedException ex ) {
@@ -130,20 +171,20 @@ public ParserResult parse() throws Exception
130171 throw ex ;
131172 }
132173
133- /* Parsing failed at some point*/
134- if (parseError == ParsingErrors .PARSING_ERROR )
135- {
136- String errDes = String .format ("Parsing error: '%s' is not '%s'." ,
137- (isEOF () == true ) ? "<EOF>" : this .lastLineRead (),
138- parseError .getTag ());
139- onParsingError (errDes , result );
140- throw new ParserException (errDes );
141- }
142-
143174 onParsingSuccess (result );
144175 return result ;
145176 }
146177
178+ /** Generates a Parser Exception object for subclasses to use.
179+ * This ensures a consistent Exception description.
180+ */
181+ protected ParserException genParserException (String field )
182+ {
183+ String errDes = String .format ("Invalid '%s' in line '%s'." ,
184+ field , this .lastLineRead ());
185+ return new ParserException (errDes );
186+ }
187+
147188 /**
148189 * Checks if End of File has been reached.
149190 */
0 commit comments