/* Copyright (c) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gdata.util;
import com.google.gdata.util.common.base.Preconditions;
/**
* This is the parent class of all error domain classes.
* Error domain classes package up a group of related error codes
* (and associated information)
* into an error domain with a unique name,
* by default the fully qualified name of the class.
*
* Create an error domain as follows:
* <ul>
* <li>Subclass ErrorDomain.
* <li>In the subclass, provide an empty private constructor and
* a {@code public static final} variable named {@code ERR}
* with the same type as the subclass; initialize it to an
* instance of the subclass. (This is eager singleton
* initialization.)
* <li>Alternatively, if you want to specify a non-default
* domain name, use {@code super("foo")} in the constructor.
* <li>Declare {@code public final ErrorCode} fields
* thus: {@code public final ErrorCode
* foo = new ErrorCode("foo")}
* (Note: not {@static}).
* <li>Append to each field declaration
* optional calls to {@link ErrorCode#withInternalReason}, {@link
* ErrorCode#withExtendedHelp}, or {@link ErrorCode#withSendReport}.
* </ul>
* <p>Here's a complete example:
* <pre>
* public class FooErrorDomain extends ErrorDomain {
* private FooErrorDomain() {
* super("Foo");
* }
*
* public static final FooErrorDomain ERR = new FooErrorDomain();
*
* public final ErrorCode bar = new ErrorCode("brokenBar")
* .withInternalReason("Bar is not working yet");
*
* public final ErrorCode unsupported = new ErrorCode("unsupported")
* .withInternalReason("Requested key is not supported");
*
* public final ErrorCode invalid = new ErrorCode("invalidValue")
* .withInternalReason("Invalid value for attribute")
* .withExtendedHelp("http://www.google.com/foo/validAttributes.html");
*
* }
* </pre>
*
* <p>Note that all {@code with} methods return a mutated copy.
*
*
*/
public abstract class ErrorDomain {
private final String domainName;
/**
* Returns the name associated with this ErrorDomain..
*/
public String getDomainName() {
return domainName;
}
/**
* Constructs an ErrorDomain with a specified name. This can be called
* only from the constructor of a subclass. The value will appear as
* the content of the {@code domain} element in the XML error format.
*/
protected ErrorDomain(String domainName) {
this.domainName = domainName;
}
/**
* Constructs an ErrorDomain with a default eror domain name. Use
* {@link #ErrorDomain(String)} to set a different domain name.
*/
protected ErrorDomain() {
domainName = getClass().getName();
}
/**
* ErrorCode objects represent an error code within an error domain.
* An inner class is used to make it difficult to construct an ErrorCode
* that accidentally refers to the wrong subclass of ErrorDomain,
* or to have more than one ErrorDomain object of the same subclass.
*
* <p>An ErrorCode is immutable. The {@link #withInternalReason(String)},
* {@link #withExtendedHelp(String)}, and {@link #withSendReport(String)}
* methods can be used to create new ErrorCodes as modified versions of
* existing ones.
*/
public class ErrorCode implements ErrorContent {
private final String codeName;
private final String extendedHelp;
private final String internalReason;
private final String sendReport;
/**
* Construct a new error code with the given code name.
*
* @param codeName the codename of this error code, must not be null.
*/
public ErrorCode(String codeName) {
this(codeName, null, null, null);
}
/**
* Private constructor that sets all fields. Clients must use the
* {@code withFoo} methods to set fields.
*/
private ErrorCode(String codeName, String extendedHelp,
String internalReason, String sendReport) {
Preconditions.checkNotNull(codeName, "codeName");
this.codeName = codeName;
this.extendedHelp = extendedHelp;
this.internalReason = internalReason;
this.sendReport = sendReport;
}
/**
* Retrieve the name of the domain of this ErrorCode.
*/
public String getDomainName() {
return ErrorDomain.this.getDomainName();
}
/**
* Gets the name of this ErrorCode, which must be unique within its domain.
* The value will appear as the content of the {@code code} element in the
* XML error format.
*/
public String getCodeName() {
return codeName;
}
/**
* Gets the internal reason (unlocalized explanation) associated with this
* ErrorCode. The value will appear as the content of the
* {@code internalReason} element in the XML error format.
*/
public String getInternalReason() {
return internalReason;
}
/**
* @deprecated Use {@link #withInternalReason(String)} instead.
*/
@Deprecated
public ErrorCode setInternalReason(String newInternalReason) {
return withInternalReason(newInternalReason);
}
/**
* Returns a copy of this ErrorCode with the given internal reason
* (un-internationalized explanation) set. The value will appear as the
* content of the {@code internalReason} element in the XML error format.
*/
public ErrorCode withInternalReason(String newInternalReason) {
return new ErrorCode(
codeName, extendedHelp, newInternalReason, sendReport);
}
/**
* Gets the extended help URI. This can be used to retrieve a
* detailed explanation of the error code. The value will appear
* as the content of the {@code extendedHelp} element in the XML
* error format.
*/
public String getExtendedHelp() {
return extendedHelp;
}
/**
* Returns a copy of this ErrorCode with the given extended help URI set.
* This can be used to provide a detailed explanation of the error code.
* The value will appear as the content of the {@code extendedHelp} element
* in the XML error format.
*/
public ErrorCode withExtendedHelp(String newExtendedHelp) {
return new ErrorCode(
codeName, newExtendedHelp, internalReason, sendReport);
}
/**
* Gets the URI to which a report should be sent when this error
* is received. The value will appear as the content of the
* {@code sendReport} element in the XML error format.
*/
public String getSendReport() {
return sendReport;
}
/**
* Returns a copy of this ErrorCode with the given send report URI set.
* This can be used to provide a URI to which a report should be sent when
* the error is received. The value will appear as the content of the
* {@code sendReport} element in the XML error format.
*/
public ErrorCode withSendReport(String newSendReport) {
return new ErrorCode(
codeName, extendedHelp, internalReason, newSendReport);
}
// Local properties of error content that error codes do not specify.
public String getLocation() {
return null;
}
public LocationType getLocationType() {
return null;
}
public String getDebugInfo() {
return null;
}
}
}