001: /* ValueConstraint
002: *
003: * $Id: Constraint.java 4661 2006-09-25 23:11:16Z paul_jack $
004: *
005: * Created on Mar 29, 2004
006: *
007: * Copyright (C) 2004 Internet Archive.
008: *
009: * This file is part of the Heritrix web crawler (crawler.archive.org).
010: *
011: * Heritrix is free software; you can redistribute it and/or modify
012: * it under the terms of the GNU Lesser Public License as published by
013: * the Free Software Foundation; either version 2.1 of the License, or
014: * any later version.
015: *
016: * Heritrix is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019: * GNU Lesser Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser Public License
022: * along with Heritrix; if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: */
025: package org.archive.crawler.settings;
026:
027: import java.io.Serializable;
028: import java.text.MessageFormat;
029: import java.util.ArrayList;
030: import java.util.logging.Level;
031:
032: /**
033: * Superclass for constraints that can be set on attribute definitions.
034: * <p>
035: * Constraints will be checked against attribute values. If a constraint check
036: * fails, an object of type FailedCheck is returned containing information that
037: * can be used to build meaningful information to the user.
038: * <p>
039: * A constraint has one of three levels:
040: * <ul>
041: * <li>{@link java.util.logging.Level#SEVERE}The attribute could not be set
042: * whatsoever.
043: * <li>{@link java.util.logging.Level#WARNING}The attribute is illegal i
044: * CrawlJobs, but could be set in profiles. Mostly used as holder value for
045: * settings that should be changed for every entity running a crawl.
046: * <li>{@link java.util.logging.Level#INFO}The attribute has a legal value,
047: * but is outside the bounds of what are considered a reasonable value. The user
048: * could be warned that she should investigate if the value actally is what she
049: * wants it be.
050: * </ul>
051: *
052: * @author John Erik Halse
053: */
054: public abstract class Constraint implements Comparable<Constraint>,
055: Serializable {
056: private final Level severity;
057: private final String msg;
058:
059: /** Constructs a new Constraint.
060: *
061: * @param level the level for this constraint.
062: * @param msg default message to return if the check fails.
063: */
064: public Constraint(Level level, String msg) {
065: if (level != Level.SEVERE && level != Level.WARNING
066: && level != Level.INFO) {
067: throw new IllegalArgumentException("Illegal level: "
068: + level.getName());
069: }
070: this .severity = level;
071: this .msg = msg;
072: }
073:
074: /**
075: * Run the check.
076: *
077: * @param owner the ComplexType owning the attribute to check.
078: * @param definition the definition to check the attribute against.
079: * @param value the value to check.
080: * @return null if ok, or an instance of {@link FailedCheck}if the check
081: * failed.
082: */
083: public final FailedCheck check(CrawlerSettings settings,
084: ComplexType owner, Type definition, Object value) {
085: return innerCheck(settings, owner, definition, value);
086: }
087:
088: /** The method all subclasses should implement to do the actual checking.
089: *
090: * @param owner the ComplexType owning the attribute to check.
091: * @param definition the definition to check the attribute against.
092: * @param value the value to check.
093: * @return null if ok, or an instance of {@link FailedCheck}if the check
094: * failed.
095: */
096: public abstract FailedCheck innerCheck(CrawlerSettings settings,
097: ComplexType owner, Type definition, Object value);
098:
099: /** Get the default message to return if a check fails.
100: *
101: * @return the default message to return if a check fails.
102: */
103: protected String getDefaultMessage() {
104: return msg;
105: }
106:
107: /** Objects of this class represents failed constraint checks.
108: *
109: * @author John Erik Halse
110: */
111: public class FailedCheck {
112: private final String msg;
113: private final CrawlerSettings settings;
114: private final ComplexType owner;
115: private final Type definition;
116: private final Object value;
117: protected final ArrayList<Object> messageArguments = new ArrayList<Object>();
118:
119: /**
120: * Construct a new FailedCheck object.
121: *
122: * @param settings the CrawlerSettings object for which this check was
123: * executed.
124: * @param owner the ComplexType owning the attribute to check.
125: * @param definition the definition to check the attribute against.
126: * @param value the value to check.
127: * @param msg a message describing what went wrong and possibly hints to
128: * the user on how to fix it.
129: */
130: public FailedCheck(CrawlerSettings settings, ComplexType owner,
131: Type definition, Object value, String msg) {
132: this .msg = msg;
133: this .settings = settings;
134: this .owner = owner;
135: this .definition = definition;
136: this .value = value;
137: this .messageArguments.add(definition.getName());
138: this .messageArguments.add(value);
139: this .messageArguments.add(owner.getName());
140: }
141:
142: /**
143: * Construct a new FailedCheck object using the constraints default
144: * message.
145: *
146: * @param settings the CrawlerSettings object for which this check was
147: * executed.
148: * @param owner the ComplexType owning the attribute to check.
149: * @param definition the definition to check the attribute against.
150: * @param value the value to check.
151: */
152: public FailedCheck(CrawlerSettings settings, ComplexType owner,
153: Type definition, Object value) {
154: this (settings, owner, definition, value,
155: getDefaultMessage());
156: }
157:
158: /** Get the error message.
159: *
160: * @return the error message.
161: */
162: public String getMessage() {
163: return MessageFormat
164: .format(msg, messageArguments.toArray());
165: }
166:
167: /** Get the severity level.
168: *
169: * @return the severity level.
170: */
171: public Level getLevel() {
172: return severity;
173: }
174:
175: /** Get the definition for the checked attribute.
176: *
177: * @return the definition for the checked attribute.
178: */
179: public Type getDefinition() {
180: return definition;
181: }
182:
183: /** Get the value of the checked attribute.
184: *
185: * @return the value of the checked attribute.
186: */
187: public Object getValue() {
188: return value;
189: }
190:
191: /** Get the {@link ComplexType} owning the checked attribute.
192: *
193: * @return the {@link ComplexType} owning the checked attribute.
194: */
195: public ComplexType getOwner() {
196: return owner;
197: }
198:
199: /** Get the {@link CrawlerSettings} for the checked attribute.
200: *
201: * @return the {@link CrawlerSettings} for the checked attribute.
202: */
203: public CrawlerSettings getSettings() {
204: return settings;
205: }
206:
207: /** Returns a human readeable string for the failed check.
208: * Returns the same as {@link #getMessage()}
209: *
210: * @return A human readeable string for the failed check.
211: */
212: public String toString() {
213: return getMessage();
214: }
215: }
216:
217: /** Compare this constraints level to another constraint.
218: * This method is implemented to let constraints be sorted with the highest
219: * level first.
220: *
221: * @param o a Constraint to compare to.
222: */
223: public int compareTo(Constraint o) {
224: Constraint c = (Constraint) o;
225: return c.severity.intValue() - severity.intValue();
226: }
227:
228: }
|