📄 ifheader.java
字号:
*/ private IfHeaderList parseUntagged(StringReader reader) { IfHeaderList list = new IfHeaderList(); try { while (true) { // read next non-whitespace reader.mark(1); int c = readWhiteSpace(reader); if (c < 0) { // end of input, no more IfLists break; } else if (c == '(') { // start of an IfList, parse list.add(parseIfList(reader)); } else if (c == '<') { // start of a tag, return current list reader.reset(); break; } else { // unexpected character // catchup to end of input or start of an IfList logIllegalState("Untagged", c, "(", reader); } } } catch (IOException ioe) { log.error("parseUntagged: Problem parsing If header: "+ioe.toString()); } return list; } /** * Parses an <em>IfList</em> in the <em>If</em> header. This method * implements the <em>Tagged</em> production given in the class comment : * <pre> IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } . * </pre> * * @param reader The <code>StringReader</code> to read from for parsing * * @return The {@link IfList} for the input <em>IfList</em>. * * @throws IOException if a problem occurrs during reading. */ private IfList parseIfList(StringReader reader) throws IOException { IfList res = new IfList(); boolean positive = true; String word; ReadLoop: while (true) { int nextChar = readWhiteSpace(reader); switch (nextChar) { case 'N': case 'n': // read not // check whether o or O int not = reader.read(); if (not != 'o' && not != 'O') { logIllegalState("IfList-Not", not, "o", null); break; } // check whether t or T not = reader.read(); if (not !='t' || not != 'T') { logIllegalState("IfList-Not", not, "t", null); break; } // read Not ok positive = false; break; case '<': // state token word = readWord(reader, '>'); if (word != null) { res.add(new IfListEntryToken(word, positive)); // also add the token to the list of all tokens if (positive) { allTokens.add(word); } else { allNotTokens.add(word); } positive = true; } break; case '[': // etag word = readWord(reader, ']'); if (word != null) { res.add(new IfListEntryEtag(word, positive)); positive = true; } break; case ')': // correct end of list, end the loop log.debug("parseIfList: End of If list, terminating loop"); break ReadLoop; default: logIllegalState("IfList", nextChar, "nN<[)", reader); // abort loop if EOF if (nextChar < 0) { break ReadLoop; } break; } } // return the current list anyway return res; } /** * Returns the first non-whitespace character from the reader or -1 if * the end of the reader is encountered. * * @param reader The <code>Reader</code> to read from * * @return The first non-whitespace character or -1 in case of EOF. * * @throws IOException if a problem occurrs during reading. */ private int readWhiteSpace(Reader reader) throws IOException { int c = reader.read(); while (c >= 0 && Character.isWhitespace((char) c)) { c = reader.read(); } return c; } /** * Reads from the input until the end character is encountered and returns * the string upto but not including this end character. If the end of input * is reached before reading the end character <code>null</code> is * returned. * <p> * Note that this method does not support any escaping. * * @param reader The <code>Reader</code> to read from * @param end The ending character limitting the word. * * @return The string read upto but not including the ending character or * <code>null</code> if the end of input is reached before the ending * character has been read. * * @throws IOException if a problem occurrs during reading. */ private String readWord(Reader reader, char end) throws IOException { StringBuffer buf = new StringBuffer(); // read the word value int c = reader.read(); for (; c >= 0 && c != end; c=reader.read()) { buf.append((char) c); } // check whether we succeeded if (c < 0) { log.error("readWord: Unexpected end of input reading word"); return null; } // build the string and return it return buf.toString(); } /** * Logs an unexpected character with the corresponding state and list of * expected characters. If the reader parameter is not null, characters * are read until either the end of the input is reached or any of the * characters in the expChar string is read. * * @param state The name of the current parse state. This method logs this * name in the message. The intended value would probably be the * name of the EBNF production during which the error occurrs. * @param effChar The effective character read. * @param expChar The list of characters acceptable in the current state. * @param reader The reader to be caught up to any of the expected * characters. If <code>null</code> the input is not caught up to * any of the expected characters (of course ;-). */ private void logIllegalState(String state, int effChar, String expChar, StringReader reader) { // format the effective character to be logged String effString = (effChar < 0) ? "<EOF>" : String.valueOf((char) effChar); // log the error log.error("logIllegalState: Unexpected character '"+effString+" in state "+state+", expected any of "+expChar); // catch up if a reader is given if (reader != null && effChar >= 0) { try { log.debug("logIllegalState: Catch up to any of "+expChar); do { reader.mark(1); effChar = reader.read(); } while (effChar >= 0 && expChar.indexOf(effChar) < 0); if (effChar >= 0) { reader.reset(); } } catch (IOException ioe) { log.error("logIllegalState: IO Problem catching up to any of "+expChar); } } } //---------- internal If header structure ---------------------------------- /** * The <code>IfListEntry</code> abstract class is the base class for * entries in an <em>IfList</em> production. This abstract base class * provides common functionality to both types of entries, namely tokens * enclosed in angle brackets (<code>< ></code>) and etags enclosed * in square brackets (<code>[ ]</code>). */ private static abstract class IfListEntry { /** * The entry string value - the semantics of this value depends on the * implementing class. */ protected final String value; /** Flag to indicate, whether this is a positive match or not */ protected final boolean positive; /** The cached result of the {@link #toString} method. */ protected String stringValue; /** * Sets up the final fields of this abstract class. The meaning of * value parameter depends solely on the implementing class. From the * point of view of this abstract class, it is simply a string value. * * @param value The string value of this instance * @param positive <code>true</code> if matches are positive */ protected IfListEntry(String value, boolean positive) { this.value = value; this.positive = positive; } /** * Matches the value from the parameter to the internal string value. * If the parameter and the {@link #value} field match, the method * returns <code>true</code> for positive matches and <code>false</code> * for negative matches. * <p> * This helper method can be called by implementations to evaluate the * concrete match on the correct value parameter. See * {@link #match(String, String)} for the external API method. * * @param value The string value to compare to the {@link #value} * field. * * @return <code>true</code> if the value parameter and the * {@link #value} field match and the {@link #positive} field is * <code>true</code> or if the values do not match and the * {@link #positive} field is <code>false</code>. */ protected boolean match(String value) { return positive == this.value.equals(value); } /** * Matches the entry's value to the the token or etag. Depending on the * concrete implementation, only one of the parameters may be evaluated * while the other may be ignored. * <p> * Implementing METHODS may call the helper method {@link #match(String)} * for the actual matching. * * @param token The token value to compare * @param etag The etag value to compare * * @return <code>true</code> if the token/etag matches the <em>IfList</em> * entry. */ public abstract boolean match(String token, String etag); /** * Returns a short type name for the implementation. This method is * used by the {@link #toString} method to build the string representation * if the instance. * * @return The type name of the implementation. */ protected abstract String getType(); /** * Returns the value of this entry. * * @return the value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -