
Thank you Rick. FYI, you could replace the comparison of this.args and other.args (about 10 lines) with just Arrays.equals(this.args, other.args). Moreover, you could implement hashCode as follows, which correct and efficient at the same time. Having args contribute to the hashCode is a waste of time. @Override public int hashCode() { return e.hashCode(); } How about renaming ResourceMessage as MessageParameterObj. See also http://www.refactoring.com/catalog/introduceParameterObject.html Cheers, Rick Beton wrote:
I have developed the idea a bit further. I think ResourceMessage is a better name (Message could mean too many other things). This is my contribution for you to include in the API if you want to.
Regards, Rick
package ch.qos.cal10n;
import java.io.Serializable; import java.util.Locale;
/** * Holds a resource message with the locale lookup deferred until it is needed * or until the locale is known. Instances are immutable so are safe to use as * Exception data or share between threads. Note that the immutability is * actually dependent on the supplied args themselves being immutable. If * ResourceMessage instances are created that contain parameters that are * mutable, the results could be unpredictable. * * @author Rick Beton */ public final class ResourceMessage implements Serializable { private static final long serialVersionUID = 6660897864328889682L;
private final Enum<?> e; private final Object[] args; // cache the result of toString private transient String string = null; // cache the result of hashCode private transient int hashcode = 0;
/** * Constructs an instance. * * @param e * the key for the corresponding resource. * @param args * any message parameters, as required. */ public ResourceMessage(Enum<?> e, Object... args) { this.e = e; if (args != null) { // take defensive copy this.args = new Object[args.length]; System.arraycopy(args, 0, this.args, 0, args.length); } else { this.args = null; } }
/** * Gets the localized message from the resource bundle, using the specified * locale. * * @return the message for the user */ public String getLocalizedMessage(Locale locale) { final IMessageConveyor mc = new MessageConveyor(locale); return mc.getMessage(e, args); }
@Override public String toString() { if (string == null) { final StringBuilder b = new StringBuilder("Message("); b.append(e.name <http://e.name>()); b.append(", ["); if (args != null) { String comma = ""; for (Object o : args) { b.append(comma).append(o); comma = ", "; } } b.append("])"); // there may be a thread race here but the outcome is never // uncertain string = b.toString(); } return string; }
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj.getClass() != ResourceMessage.class) { return false; }
final ResourceMessage other = (ResourceMessage) obj; if (!this.e.equals(other.e)) { return false; } else if (this.args == null && other.args == null) { return true; } else if (this.args == null || other.args == null) { return false; } else if (this.args.length != other.args.length) { return false; }
for (int i = 0; i < args.length; i++) { if (this.args[i] == null && other.args[i] == null) { // ok } else if (this.args[i] == null && other.args[i] != null) { return false; } else if (!this.args[i].equals(other.args[i])) { return false; } } return true; }
@Override public int hashCode() { if (hashcode == 0) { int newHashCode = 0; newHashCode = e.hashCode(); if (args != null) { for (Object o : args) { if (o != null) { newHashCode ^= o.hashCode(); } } } // there may be a thread race here but the outcome is never // uncertain hashcode = newHashCode; } return hashcode; } }
-- Ceki Gülcü Logback: The reliable, generic, fast and flexible logging framework for Java. http://logback.qos.ch