/* * ----------------------------------------------------------------------- * Copyright © 2013-2016 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (ParseLog.java) is part of project Time4J. * * Time4J is free software: You can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * * Time4J is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Time4J. If not, see <http://www.gnu.org/licenses/>. * ----------------------------------------------------------------------- */ package net.time4j.format.expert; import net.time4j.engine.ChronoEntity; import java.text.ParsePosition; /** * <p>Represents a log for the current status and error informations during * parsing. </p> * * <p>Note: This class is not <i>thread-safe</i>. Therefore a new instance * is to be created per thread (usually per parsing process). </p> * * @author Meno Hochschild * @since 3.0 * @doctags.concurrency {mutable} */ /*[deutsch] * <p>Zeichnet den Status und Fehlermeldungen beim Parsen auf. </p> * * <p>Hinweis: Diese Klasse ist nicht <i>thread-safe</i>, deshalb ist * pro Thread jeweils eine neue Instanz zu erzeugen (in der Regel pro * Parse-Vorgang). </p> * * @author Meno Hochschild * @since 3.0 * @doctags.concurrency {mutable} */ public class ParseLog { //~ Instanzvariablen -------------------------------------------------- private ParsePosition pp; private String errorMessage; private ChronoEntity<?> rawValues; private Boolean daylightSaving; private boolean warning; //~ Konstruktoren ----------------------------------------------------- /** * <p>Standard constructor with start position at begin of text. </p> * * @since 3.0 */ /*[deutsch] * <p>Standard-Konstruktor mit der Startposition am Textanfang. </p> * * @since 3.0 */ public ParseLog() { this(0); } /** * <p>Creates a new instance with given start position. </p> * * @param offset start position where parsing of text begins * @throws IllegalArgumentException if the start position is negative * @since 3.0 */ /*[deutsch] * <p>Konstruiert eine neue Instanz mit der angegebenen Startposition. </p> * * @param offset start position where parsing of text begins * @throws IllegalArgumentException if the start position is negative * @since 3.0 */ public ParseLog(int offset) { super(); if (offset < 0) { throw new IllegalArgumentException("Undefined: " + offset); } this.pp = new ParsePosition(offset); this.errorMessage = ""; this.rawValues = null; this.daylightSaving = null; this.warning = false; } /** * Initialisiert mit Hilfe des JDK-Äquivalent. </p> * * @param pp new {@code ParsePosition} */ ParseLog(ParsePosition pp) { super(); if (pp.getIndex() < 0) { throw new IllegalArgumentException("Undefined position: " + pp.getIndex()); } // now overtaking the argument itself (mutable reference) pp.setErrorIndex(-1); this.pp = pp; this.errorMessage = ""; this.rawValues = null; this.daylightSaving = null; this.warning = false; } //~ Methoden ---------------------------------------------------------- /** * <p>Returns the current position of the parser. </p> * * @return int ({@code >= 0}) * @since 3.0 */ /*[deutsch] * <p>Gibt die aktuelle Position des Parsers wieder. </p> * * @return int ({@code >= 0}) * @since 3.0 */ public int getPosition() { return this.pp.getIndex(); } /** * <p>Queries if an error has occurred. </p> * * @return boolean * @since 3.0 */ /*[deutsch] * <p>Ermittelt, ob ein Fehler aufgetreten ist. </p> * * @return boolean * @since 3.0 */ public boolean isError() { return (this.pp.getErrorIndex() != -1); } /** * <p>Returns the position of error in text. </p> * * @return int ({@code >= 0} in case of error else {@code -1}) * @since 3.0 */ /*[deutsch] * <p>Gibt die fehlerhafte Stelle im Text an. </p> * * @return int ({@code >= 0} in case of error else {@code -1}) * @since 3.0 */ public int getErrorIndex() { return this.pp.getErrorIndex(); } /** * <p>Returns an error message. </p> * * @return String (empty if there is no error) * @since 3.0 */ /*[deutsch] * <p>Gibt eine Fehlerbeschreibung an. </p> * * @return String (empty if there is no error) * @since 3.0 */ public String getErrorMessage() { return this.errorMessage; } /** * <p>Yields the parsed raw data as chronological entity. </p> * * @return parsed values as mutable serializable map-like entity without chronology * @since 3.0 */ /*[deutsch] * <p>Liefert die interpretierten Rohdaten. </p> * * @return parsed values as mutable serializable map-like entity without chronology * @since 3.0 */ public ChronoEntity<?> getRawValues() { if (this.rawValues == null) { this.rawValues = new ParsedValues(0, false); } return this.rawValues; } /** * <p>Debugging support. </p> */ /*[deutsch] * <p>Debugging-Unterstützung. </p> */ @Override public String toString() { StringBuilder sb = new StringBuilder(128); sb.append("[position="); sb.append(this.getPosition()); sb.append(", error-index="); sb.append(this.getErrorIndex()); sb.append(", error-message=\""); sb.append(this.errorMessage); sb.append('\"'); if (this.warning) { sb.append(", warning-active"); } if (this.rawValues != null) { sb.append(", raw-values="); sb.append(this.rawValues); } if (this.daylightSaving != null) { sb.append(", daylight-saving="); sb.append(this.daylightSaving); } sb.append(']'); return sb.toString(); } /** * <p>Sets the current position of the parser to given new position. </p> * * @param position new parse position ({@code >= 0}) * @throws IllegalArgumentException if given position is negative * @since 3.0 */ /*[deutsch] * <p>Setzt die aktuelle Position des Parsers neu. </p> * * @param position new parse position ({@code >= 0}) * @throws IllegalArgumentException if given position is negative * @since 3.0 */ public void setPosition(int position) { if (position < 0) { throw new IllegalArgumentException("Undefined position: " + position); } this.pp.setIndex(position); } /** * <p>Sets an error information. </p> * * @param errorIndex error index in parsed text * @param errorMessage error message maybe empty * @throws IllegalArgumentException if given error index is negative * @since 3.0 */ /*[deutsch] * <p>Setzt eine Fehlerinformation. </p> * * @param errorIndex error index in parsed text * @param errorMessage error message maybe empty * @throws IllegalArgumentException if given error index is negative * @since 3.0 */ public void setError( int errorIndex, String errorMessage ) { if (errorIndex >= 0) { this.errorMessage = ( ((errorMessage == null) || errorMessage.isEmpty()) ? ("Error occurred at position: " + errorIndex) : errorMessage); } else { throw new IllegalArgumentException("Undefined error index: " + errorIndex); } this.pp.setErrorIndex(errorIndex); } /** * <p>Sets a warning to indicate if the current formatter should try * to use default values for chronological elements which could not * be parsed. </p> * * <p>If there is no error present then an unspecific error message * will be created, too. Only customized {@code ChronoParser}-objects * might need to call this method. </p> * * @since 3.0 * @see ChronoParser */ /*[deutsch] * <p>Setzt eine Warnung, um anzuzeigen, daß der aktuelle * Formatierer versuchen sollte, Standardwerte für chronologische * Elemente zu verwenden, die nicht interpretiert werden konnten. </p> * * <p>Wenn kein Fehler gesetzt ist, dann wird automatisch eine * unspezifizierte Fehlermeldung generiert. Nur spezielle * {@code ChronoParser}-Objekte rufen diese Methode bei Bedarf auf. </p> * * @since 3.0 * @see ChronoParser */ public void setWarning() { if (!this.isError()) { this.errorMessage = "Warning state active."; this.pp.setErrorIndex(this.getPosition()); } this.warning = true; } /** * <p>Reuses this instance for next parse process. </p> * * @since 3.0 */ /*[deutsch] * <p>Bereitet diese Instanz auf die Wiederverwendung für einen * neuen Interpretierungsvorgang vor. </p> * * @since 3.0 */ public void reset() { this.pp.setIndex(0); this.pp.setErrorIndex(-1); this.errorMessage = ""; this.warning = false; this.rawValues = null; this.daylightSaving = null; } /** * <p>Interne Methode. </p> * * @return parsed values, initially {@code null} */ ChronoEntity<?> getRawValues0() { return this.rawValues; } /** * <p>Löscht eine eventuell vorhandene Fehlerinformation. </p> */ void clearError() { this.pp.setErrorIndex(-1); this.errorMessage = ""; } /** * <p>Setzt die interpretierten Rohdaten. </p> * * @param rawValues parsed values */ void setRawValues(ChronoEntity<?> rawValues) { this.rawValues = rawValues; } /** * <p>Ein Zeitzonenname wurde als <i>daylightSaving</i> erkannt. </p> */ void setDaylightSaving(boolean dst) { this.daylightSaving = Boolean.valueOf(dst); } /** * <p>Wurde eine Sommer- oder Winterzeitform als Zeitzonenname gelesen? </p> * * @return {@code Boolean.TRUE} wenn Sommerzeit, {@code Boolean.FALSE} * wenn Winterzeit (Normalzeit), sonst {@code null} */ Boolean getDSTInfo() { return this.daylightSaving; } /** * <p>Ermittelt, ob eine Warnung gesetzt wurde. </p> * * @return boolean */ boolean isWarning() { return this.warning; } /** * <p>Entfernt eine Warnung. </p> */ void clearWarning() { this.warning = false; } /** * Liefert das JDK-Äquivalent. </p> * * @return ParsePosition */ ParsePosition getPP() { return this.pp; } }