home | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Errors.java)

This example Java source code file (Errors.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

annotation, cannot, class, dependency, elementsource, errors, inject, list, log, logging, message, object, override, please, reflection, string, threads, throwable, typeliteral, util

The Errors.java Java example source code

/**
 * Copyright (C) 2006 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.inject.internal;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.Equivalence;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.inject.ConfigurationException;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.util.Classes;
import com.google.inject.internal.util.SourceProvider;
import com.google.inject.internal.util.StackTraceElements;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.ElementSource;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
import com.google.inject.spi.ScopeBinding;
import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Formatter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A collection of error messages. If this type is passed as a method parameter, the method is
 * considered to have executed successfully only if new errors were not added to this collection.
 *
 * <p>Errors can be chained to provide additional context. To add context, call {@link #withSource}
 * to create a new Errors instance that contains additional context. All messages added to the
 * returned instance will contain full context.
 *
 * <p>To avoid messages with redundant context, {@link #withSource} should be added sparingly. A
 * good rule of thumb is to assume a method's caller has already specified enough context to
 * identify that method. When calling a method that's defined in a different context, call that
 * method with an errors object that includes its context.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 */
public final class Errors implements Serializable {

  private static final Logger logger = Logger.getLogger(Guice.class.getName());
  
  private static final Set<Dependency warnedDependencies =
      Collections.newSetFromMap(new ConcurrentHashMap<Dependency());

  /**
   * The root errors object. Used to access the list of error messages.
   */
  private final Errors root;

  /**
   * The parent errors object. Used to obtain the chain of source objects.
   */
  private final Errors parent;

  /**
   * The leaf source for errors added here.
   */
  private final Object source;

  /**
   * null unless (root == this) and error messages exist. Never an empty list.
   */
  private List<Message> errors; // lazy, use getErrorsForAdd()

  public Errors() {
    this.root = this;
    this.parent = null;
    this.source = SourceProvider.UNKNOWN_SOURCE;
  }

  public Errors(Object source) {
    this.root = this;
    this.parent = null;
    this.source = source;
  }

  private Errors(Errors parent, Object source) {
    this.root = parent.root;
    this.parent = parent;
    this.source = source;
  }

  /**
   * Returns an instance that uses {@code source} as a reference point for newly added errors.
   */
  public Errors withSource(Object source) {
    return source == this.source || source == SourceProvider.UNKNOWN_SOURCE
        ? this
        : new Errors(this, source);
  }

  /**
   * We use a fairly generic error message here. The motivation is to share the
   * same message for both bind time errors:
   * <pre>Guice.createInjector(new AbstractModule() {
   *   public void configure() {
   *     bind(Runnable.class);
   *   }
   * }</code>
* ...and at provide-time errors: * <pre>Guice.createInjector().getInstance(Runnable.class); * Otherwise we need to know who's calling when resolving a just-in-time * binding, which makes things unnecessarily complex. */ public Errors missingImplementation(Key key) { return addMessage("No implementation for %s was bound.", key); } public Errors jitDisabled(Key key) { return addMessage("Explicit bindings are required and %s is not explicitly bound.", key); } public Errors jitDisabledInParent(Key<?> key) { return addMessage( "Explicit bindings are required and %s would be bound in a parent injector.%n" + "Please add an explicit binding for it, either in the child or the parent.", key); } public Errors atInjectRequired(Class clazz) { return addMessage( "Explicit @Inject annotations are required on constructors," + " but %s has no constructors annotated with @Inject.", clazz); } public Errors converterReturnedNull(String stringValue, Object source, TypeLiteral<?> type, TypeConverterBinding typeConverterBinding) { return addMessage("Received null converting '%s' (bound at %s) to %s%n" + " using %s.", stringValue, convert(source), type, typeConverterBinding); } public Errors conversionTypeError(String stringValue, Object source, TypeLiteral<?> type, TypeConverterBinding typeConverterBinding, Object converted) { return addMessage("Type mismatch converting '%s' (bound at %s) to %s%n" + " using %s.%n" + " Converter returned %s.", stringValue, convert(source), type, typeConverterBinding, converted); } public Errors conversionError(String stringValue, Object source, TypeLiteral<?> type, TypeConverterBinding typeConverterBinding, RuntimeException cause) { return errorInUserCode(cause, "Error converting '%s' (bound at %s) to %s%n" + " using %s.%n" + " Reason: %s", stringValue, convert(source), type, typeConverterBinding, cause); } public Errors ambiguousTypeConversion(String stringValue, Object source, TypeLiteral<?> type, TypeConverterBinding a, TypeConverterBinding b) { return addMessage("Multiple converters can convert '%s' (bound at %s) to %s:%n" + " %s and%n" + " %s.%n" + " Please adjust your type converter configuration to avoid overlapping matches.", stringValue, convert(source), type, a, b); } public Errors bindingToProvider() { return addMessage("Binding to Provider is not allowed."); } public Errors subtypeNotProvided(Class<? extends javax.inject.Provider providerType, Class<?> type) { return addMessage("%s doesn't provide instances of %s.", providerType, type); } public Errors notASubtype(Class<?> implementationType, Class type) { return addMessage("%s doesn't extend %s.", implementationType, type); } public Errors recursiveImplementationType() { return addMessage("@ImplementedBy points to the same class it annotates."); } public Errors recursiveProviderType() { return addMessage("@ProvidedBy points to the same class it annotates."); } public Errors missingRuntimeRetention(Class<? extends Annotation> annotation) { return addMessage(format("Please annotate %s with @Retention(RUNTIME).", annotation)); } public Errors missingScopeAnnotation(Class<? extends Annotation> annotation) { return addMessage(format("Please annotate %s with @ScopeAnnotation.", annotation)); } public Errors optionalConstructor(Constructor constructor) { return addMessage("%s is annotated @Inject(optional=true), " + "but constructors cannot be optional.", constructor); } public Errors cannotBindToGuiceType(String simpleName) { return addMessage("Binding to core guice framework type is not allowed: %s.", simpleName); } public Errors scopeNotFound(Class<? extends Annotation> scopeAnnotation) { return addMessage("No scope is bound to %s.", scopeAnnotation); } public Errors scopeAnnotationOnAbstractType( Class<? extends Annotation> scopeAnnotation, Class type, Object source) { return addMessage("%s is annotated with %s, but scope annotations are not supported " + "for abstract types.%n Bound at %s.", type, scopeAnnotation, convert(source)); } public Errors misplacedBindingAnnotation(Member member, Annotation bindingAnnotation) { return addMessage("%s is annotated with %s, but binding annotations should be applied " + "to its parameters instead.", member, bindingAnnotation); } private static final String CONSTRUCTOR_RULES = "Classes must have either one (and only one) constructor " + "annotated with @Inject or a zero-argument constructor that is not private."; public Errors missingConstructor(Class<?> implementation) { return addMessage("Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES, implementation); } public Errors tooManyConstructors(Class<?> implementation) { return addMessage("%s has more than one constructor annotated with @Inject. " + CONSTRUCTOR_RULES, implementation); } public Errors constructorNotDefinedByType(Constructor<?> constructor, TypeLiteral type) { return addMessage("%s does not define %s", type, constructor); } public Errors duplicateScopes(ScopeBinding existing, Class<? extends Annotation> annotationType, Scope scope) { return addMessage("Scope %s is already bound to %s at %s.%n Cannot bind %s.", existing.getScope(), annotationType, existing.getSource(), scope); } public Errors voidProviderMethod() { return addMessage("Provider methods must return a value. Do not return void."); } public Errors missingConstantValues() { return addMessage("Missing constant value. Please call to(...)."); } public Errors cannotInjectInnerClass(Class<?> type) { return addMessage("Injecting into inner classes is not supported. " + "Please use a 'static' class (top-level or nested) instead of %s.", type); } public Errors duplicateBindingAnnotations(Member member, Class<? extends Annotation> a, Class b) { return addMessage("%s has more than one annotation annotated with @BindingAnnotation: " + "%s and %s", member, a, b); } public Errors staticInjectionOnInterface(Class<?> clazz) { return addMessage("%s is an interface, but interfaces have no static injection points.", clazz); } public Errors cannotInjectFinalField(Field field) { return addMessage("Injected field %s cannot be final.", field); } public Errors cannotInjectAbstractMethod(Method method) { return addMessage("Injected method %s cannot be abstract.", method); } public Errors cannotInjectNonVoidMethod(Method method) { return addMessage("Injected method %s must return void.", method); } public Errors cannotInjectMethodWithTypeParameters(Method method) { return addMessage("Injected method %s cannot declare type parameters of its own.", method); } public Errors duplicateScopeAnnotations( Class<? extends Annotation> a, Class b) { return addMessage("More than one scope annotation was found: %s and %s.", a, b); } public Errors recursiveBinding() { return addMessage("Binding points to itself."); } public Errors bindingAlreadySet(Key<?> key, Object source) { return addMessage("A binding to %s was already configured at %s.", key, convert(source)); } public Errors jitBindingAlreadySet(Key<?> key) { return addMessage("A just-in-time binding to %s was already configured on a parent injector.", key); } public Errors childBindingAlreadySet(Key<?> key, Set sources) { Formatter allSources = new Formatter(); for (Object source : sources) { if (source == null) { allSources.format("%n (bound by a just-in-time binding)"); } else { allSources.format("%n bound at %s", source); } } Errors errors = addMessage( "Unable to create binding for %s." + " It was already configured on one or more child injectors or private modules" + "%s%n" + " If it was in a PrivateModule, did you forget to expose the binding?", key, allSources.out()); return errors; } public Errors errorCheckingDuplicateBinding(Key<?> key, Object source, Throwable t) { return addMessage( "A binding to %s was already configured at %s and an error was thrown " + "while checking duplicate bindings. Error: %s", key, convert(source), t); } public Errors errorInjectingMethod(Throwable cause) { return errorInUserCode(cause, "Error injecting method, %s", cause); } public Errors errorNotifyingTypeListener(TypeListenerBinding listener, TypeLiteral<?> type, Throwable cause) { return errorInUserCode(cause, "Error notifying TypeListener %s (bound at %s) of %s.%n" + " Reason: %s", listener.getListener(), convert(listener.getSource()), type, cause); } public Errors errorInjectingConstructor(Throwable cause) { return errorInUserCode(cause, "Error injecting constructor, %s", cause); } public Errors errorInProvider(Throwable cause) { Throwable unwrapped = unwrap(cause); return errorInUserCode(unwrapped, "Error in custom provider, %s", unwrapped); } public Errors errorInUserInjector( MembersInjector<?> listener, TypeLiteral type, RuntimeException cause) { return errorInUserCode(cause, "Error injecting %s using %s.%n" + " Reason: %s", type, listener, cause); } public Errors errorNotifyingInjectionListener( InjectionListener<?> listener, TypeLiteral type, RuntimeException cause) { return errorInUserCode(cause, "Error notifying InjectionListener %s of %s.%n" + " Reason: %s", listener, type, cause); } public Errors exposedButNotBound(Key<?> key) { return addMessage("Could not expose() %s, it must be explicitly bound.", key); } public Errors keyNotFullySpecified(TypeLiteral<?> typeLiteral) { return addMessage("%s cannot be used as a key; It is not fully specified.", typeLiteral); } public Errors errorEnhancingClass(Class<?> clazz, Throwable cause) { return errorInUserCode(cause, "Unable to method intercept: %s", clazz); } public static Collection<Message> getMessagesFromThrowable(Throwable throwable) { if (throwable instanceof ProvisionException) { return ((ProvisionException) throwable).getErrorMessages(); } else if (throwable instanceof ConfigurationException) { return ((ConfigurationException) throwable).getErrorMessages(); } else if (throwable instanceof CreationException) { return ((CreationException) throwable).getErrorMessages(); } else { return ImmutableSet.of(); } } public Errors errorInUserCode(Throwable cause, String messageFormat, Object... arguments) { Collection<Message> messages = getMessagesFromThrowable(cause); if (!messages.isEmpty()) { return merge(messages); } else { return addMessage(cause, messageFormat, arguments); } } private Throwable unwrap(Throwable runtimeException) { if(runtimeException instanceof Exceptions.UnhandledCheckedUserException) { return runtimeException.getCause(); } else { return runtimeException; } } public Errors cannotInjectRawProvider() { return addMessage("Cannot inject a Provider that has no type parameter"); } public Errors cannotInjectRawMembersInjector() { return addMessage("Cannot inject a MembersInjector that has no type parameter"); } public Errors cannotInjectTypeLiteralOf(Type unsupportedType) { return addMessage("Cannot inject a TypeLiteral of %s", unsupportedType); } public Errors cannotInjectRawTypeLiteral() { return addMessage("Cannot inject a TypeLiteral that has no type parameter"); } public Errors cannotProxyClass(Class<?> expectedType) { return addMessage( "Tried proxying %s to support a circular dependency, but it is not an interface.", expectedType); } public Errors circularDependenciesDisabled(Class<?> expectedType) { return addMessage( "Found a circular dependency involving %s, and circular dependencies are disabled.", expectedType); } public void throwCreationExceptionIfErrorsExist() { if (!hasErrors()) { return; } throw new CreationException(getMessages()); } public void throwConfigurationExceptionIfErrorsExist() { if (!hasErrors()) { return; } throw new ConfigurationException(getMessages()); } public void throwProvisionExceptionIfErrorsExist() { if (!hasErrors()) { return; } throw new ProvisionException(getMessages()); } private Message merge(Message message) { List<Object> sources = Lists.newArrayList(); sources.addAll(getSources()); sources.addAll(message.getSources()); return new Message(sources, message.getMessage(), message.getCause()); } public Errors merge(Collection<Message> messages) { for (Message message : messages) { addMessage(merge(message)); } return this; } public Errors merge(Errors moreErrors) { if (moreErrors.root == root || moreErrors.root.errors == null) { return this; } merge(moreErrors.root.errors); return this; } public List<Object> getSources() { List<Object> sources = Lists.newArrayList(); for (Errors e = this; e != null; e = e.parent) { if (e.source != SourceProvider.UNKNOWN_SOURCE) { sources.add(0, e.source); } } return sources; } public void throwIfNewErrors(int expectedSize) throws ErrorsException { if (size() == expectedSize) { return; } throw toException(); } public ErrorsException toException() { return new ErrorsException(this); } public boolean hasErrors() { return root.errors != null; } public Errors addMessage(String messageFormat, Object... arguments) { return addMessage(null, messageFormat, arguments); } private Errors addMessage(Throwable cause, String messageFormat, Object... arguments) { String message = format(messageFormat, arguments); addMessage(new Message(getSources(), message, cause)); return this; } public Errors addMessage(Message message) { if (root.errors == null) { root.errors = Lists.newArrayList(); } root.errors.add(message); return this; } public static String format(String messageFormat, Object... arguments) { for (int i = 0; i < arguments.length; i++) { arguments[i] = Errors.convert(arguments[i]); } return String.format(messageFormat, arguments); } public List<Message> getMessages() { if (root.errors == null) { return ImmutableList.of(); } return new Ordering<Message>() { @Override public int compare(Message a, Message b) { return a.getSource().compareTo(b.getSource()); } }.sortedCopy(root.errors); } /** Returns the formatted message for an exception with the specified messages. */ public static String format(String heading, Collection<Message> errorMessages) { Formatter fmt = new Formatter().format(heading).format(":%n%n"); int index = 1; boolean displayCauses = getOnlyCause(errorMessages) == null; Map<Equivalence.Wrapper causes = Maps.newHashMap(); for (Message errorMessage : errorMessages) { int thisIdx = index++; fmt.format("%s) %s%n", thisIdx, errorMessage.getMessage()); List<Object> dependencies = errorMessage.getSources(); for (int i = dependencies.size() - 1; i >= 0; i--) { Object source = dependencies.get(i); formatSource(fmt, source); } Throwable cause = errorMessage.getCause(); if (displayCauses && cause != null) { Equivalence.Wrapper<Throwable> causeEquivalence = ThrowableEquivalence.INSTANCE.wrap(cause); if (!causes.containsKey(causeEquivalence)) { causes.put(causeEquivalence, thisIdx); fmt.format("Caused by: %s", Throwables.getStackTraceAsString(cause)); } else { int causeIdx = causes.get(causeEquivalence); fmt.format("Caused by: %s (same stack trace as error #%s)", cause.getClass().getName(), causeIdx); } } fmt.format("%n"); } if (errorMessages.size() == 1) { fmt.format("1 error"); } else { fmt.format("%s errors", errorMessages.size()); } return fmt.toString(); } /** * Returns {@code value} if it is non-null or allowed to be null. Otherwise a message is added and * an {@code ErrorsException} is thrown. */ public <T> T checkForNull(T value, Object source, Dependency dependency) throws ErrorsException { if (value != null || dependency.isNullable()) { return value; } // Hack to allow null parameters to @Provides methods, for backwards compatibility. if (dependency.getInjectionPoint().getMember() instanceof Method) { Method annotated = (Method) dependency.getInjectionPoint().getMember(); if (annotated.isAnnotationPresent(Provides.class)) { switch (InternalFlags.getNullableProvidesOption()) { case ERROR: break; // break out & let the below exception happen case IGNORE: return value; // user doesn't care about injecting nulls to non-@Nullables. case WARN: // Warn only once, otherwise we spam logs too much. if (!warnedDependencies.add(dependency)) { return value; } logger.log( Level.WARNING, "Guice injected null into {0} (a {1}), please mark it @Nullable." + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an" + " error.", new Object[] {formatParameter(dependency), convert(dependency.getKey())}); return null; // log & exit. } } } Object formattedDependency = (dependency.getParameterIndex() != -1) ? formatParameter(dependency) : StackTraceElements.forMember(dependency.getInjectionPoint().getMember()); addMessage( "null returned by binding at %s%n but %s is not @Nullable", source, formattedDependency); throw toException(); } /** * Returns the cause throwable if there is exactly one cause in {@code messages}. If there are * zero or multiple messages with causes, null is returned. */ public static Throwable getOnlyCause(Collection<Message> messages) { Throwable onlyCause = null; for (Message message : messages) { Throwable messageCause = message.getCause(); if (messageCause == null) { continue; } if (onlyCause != null && !ThrowableEquivalence.INSTANCE.equivalent(onlyCause, messageCause)) { return null; } onlyCause = messageCause; } return onlyCause; } public int size() { return root.errors == null ? 0 : root.errors.size(); } private static abstract class Converter<T> { final Class<T> type; Converter(Class<T> type) { this.type = type; } boolean appliesTo(Object o) { return o != null && type.isAssignableFrom(o.getClass()); } String convert(Object o) { return toString(type.cast(o)); } abstract String toString(T t); } private static final Collection<Converter converters = ImmutableList.of( new Converter<Class>(Class.class) { @Override public String toString(Class c) { return c.getName(); } }, new Converter<Member>(Member.class) { @Override public String toString(Member member) { return Classes.toString(member); } }, new Converter<Key>(Key.class) { @Override public String toString(Key key) { if (key.getAnnotationType() != null) { return key.getTypeLiteral() + " annotated with " + (key.getAnnotation() != null ? key.getAnnotation() : key.getAnnotationType()); } else { return key.getTypeLiteral().toString(); } } }); public static Object convert(Object o) { ElementSource source = null; if (o instanceof ElementSource) { source = (ElementSource)o; o = source.getDeclaringSource(); } return convert(o, source); } public static Object convert(Object o, ElementSource source) { for (Converter<?> converter : converters) { if (converter.appliesTo(o)) { return appendModules(converter.convert(o), source); } } return appendModules(o, source); } private static Object appendModules(Object source, ElementSource elementSource) { String modules = moduleSourceString(elementSource); if (modules.length() == 0) { return source; } else { return source + modules; } } private static String moduleSourceString(ElementSource elementSource) { // if we only have one module (or don't know what they are), then don't bother // reporting it, because the source already is going to report exactly that module. if (elementSource == null) { return ""; } List<String> modules = Lists.newArrayList(elementSource.getModuleClassNames()); // Insert any original element sources w/ module info into the path. while(elementSource.getOriginalElementSource() != null) { elementSource = elementSource.getOriginalElementSource(); modules.addAll(0, elementSource.getModuleClassNames()); } if (modules.size() <= 1) { return ""; } // Ideally we'd do: // return Joiner.on(" -> ") // .appendTo(new StringBuilder(" (via modules: "), Lists.reverse(modules)) // .append(")").toString(); // ... but for some reason we can't find Lists.reverse, so do it the boring way. StringBuilder builder = new StringBuilder(" (via modules: "); for (int i = modules.size() - 1; i >= 0; i--) { builder.append(modules.get(i)); if (i != 0) { builder.append(" -> "); } } builder.append(")"); return builder.toString(); } public static void formatSource(Formatter formatter, Object source) { ElementSource elementSource = null; if (source instanceof ElementSource) { elementSource = (ElementSource)source; source = elementSource.getDeclaringSource(); } formatSource(formatter, source, elementSource); } public static void formatSource(Formatter formatter, Object source, ElementSource elementSource) { String modules = moduleSourceString(elementSource); if (source instanceof Dependency) { Dependency<?> dependency = (Dependency) source; InjectionPoint injectionPoint = dependency.getInjectionPoint(); if (injectionPoint != null) { formatInjectionPoint(formatter, dependency, injectionPoint, elementSource); } else { formatSource(formatter, dependency.getKey(), elementSource); } } else if (source instanceof InjectionPoint) { formatInjectionPoint(formatter, null, (InjectionPoint) source, elementSource); } else if (source instanceof Class) { formatter.format(" at %s%s%n", StackTraceElements.forType((Class<?>) source), modules); } else if (source instanceof Member) { formatter.format(" at %s%s%n", StackTraceElements.forMember((Member) source), modules); } else if (source instanceof TypeLiteral) { formatter.format(" while locating %s%s%n", source, modules); } else if (source instanceof Key) { Key<?> key = (Key) source; formatter.format(" while locating %s%n", convert(key, elementSource)); } else if (source instanceof Thread) { formatter.format(" in thread %s%n", source); } else { formatter.format(" at %s%s%n", source, modules); } } public static void formatInjectionPoint(Formatter formatter, Dependency<?> dependency, InjectionPoint injectionPoint, ElementSource elementSource) { Member member = injectionPoint.getMember(); Class<? extends Member> memberType = Classes.memberType(member); if (memberType == Field.class) { dependency = injectionPoint.getDependencies().get(0); formatter.format(" while locating %s%n", convert(dependency.getKey(), elementSource)); formatter.format(" for field at %s%n", StackTraceElements.forMember(member)); } else if (dependency != null) { formatter.format(" while locating %s%n", convert(dependency.getKey(), elementSource)); formatter.format(" for %s%n", formatParameter(dependency)); } else { formatSource(formatter, injectionPoint.getMember()); } } private static String formatParameter(Dependency<?> dependency) { int ordinal = dependency.getParameterIndex() + 1; return String.format( "the %s%s parameter of %s", ordinal, getOrdinalSuffix(ordinal), StackTraceElements.forMember(dependency.getInjectionPoint().getMember())); } /** * Maps {@code 1} to the string {@code "1st"} ditto for all non-negative numbers * * @see <a href="https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers"> * https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers</a> */ private static String getOrdinalSuffix(int ordinal) { // negative ordinals don't make sense, we allow zero though because we are programmers checkArgument(ordinal >= 0); if ((ordinal / 10) % 10 == 1) { // all the 'teens' are weird return "th"; } else { // could use a lookup table? any better? switch (ordinal % 10) { case 1: return "st"; case 2: return "nd"; case 3: return "rd"; default: return "th"; } } } static class ThrowableEquivalence extends Equivalence<Throwable> { static final ThrowableEquivalence INSTANCE = new ThrowableEquivalence(); @Override protected boolean doEquivalent(Throwable a, Throwable b) { return a.getClass().equals(b.getClass()) && Objects.equal(a.getMessage(), b.getMessage()) && Arrays.equals(a.getStackTrace(), b.getStackTrace()) && equivalent(a.getCause(), b.getCause()); } @Override protected int doHash(Throwable t) { return Objects.hashCode(t.getClass().hashCode(), t.getMessage(), hash(t.getCause())); } } }

Other Java examples (source code examples)

Here is a short list of links related to this Java Errors.java source code file:



my book on functional programming

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.