Key.java
001 /*
002  * Copyright 2008-2017 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *     http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 package griffon.core.injection;
017 
018 import javax.annotation.Nonnull;
019 import javax.annotation.Nullable;
020 import java.lang.annotation.Annotation;
021 
022 import static java.util.Objects.requireNonNull;
023 
024 /**
025  @author Andres Almiray
026  @since 2.7.0
027  */
028 public class Key<T> {
029     private static final String ERROR_SOURCE_NULL = "Argument 'source' must not be null";
030     private static final String ERROR_ANNOTATION_NULL = "Argument 'annotation' must not be null";
031     private static final String ERROR_ANNOTATION_TYPE_NULL = "Argument 'annotationType' must not be null";
032 
033     private final Class<T> source;
034     private Class<? extends Annotation> annotationType;
035     private Annotation annotation;
036 
037     private Key(@Nonnull Class<T> source) {
038         this.source = requireNonNull(source, ERROR_SOURCE_NULL);
039     }
040 
041     private Key(@Nonnull Class<T> source, @Nonnull Annotation annotation) {
042         this.source = requireNonNull(source, ERROR_SOURCE_NULL);
043         this.annotation = requireNonNull(annotation, ERROR_ANNOTATION_NULL);
044         this.annotationType = annotation.getClass();
045     }
046 
047     private Key(@Nonnull Class<T> source, @Nonnull Class<? extends Annotation> annotationType) {
048         this.source = requireNonNull(source, ERROR_SOURCE_NULL);
049         this.annotationType = requireNonNull(annotationType, ERROR_ANNOTATION_TYPE_NULL);
050     }
051 
052     @Nonnull
053     public Class<?> getSource() {
054         return source;
055     }
056 
057     @Nullable
058     public Class<? extends Annotation> getAnnotationType() {
059         return annotationType;
060     }
061 
062     @Nullable
063     public Annotation getAnnotation() {
064         return annotation;
065     }
066 
067     @Override
068     public boolean equals(Object o) {
069         if (this == o) { return true}
070         if (o == null || getClass() != o.getClass()) { return false}
071 
072         Key key = (Keyo;
073 
074         if (annotation != null) {
075             return source.equals(key.source&& annotation.equals(key.annotation);
076         }
077 
078         return source.equals(key.source&&
079             !(annotationType != null ? !annotationType.equals(key.annotationType: key.annotationType != null);
080     }
081 
082     @Override
083     public int hashCode() {
084         int result = source.hashCode();
085         if (annotation != null) {
086             result = 31 * result + annotation.hashCode();
087         else {
088             result = 31 * result + (annotationType != null ? annotationType.hashCode() 0);
089         }
090         return result;
091     }
092 
093     @Override
094     public String toString() {
095         final StringBuilder sb = new StringBuilder("Key{");
096         sb.append("source=").append(source);
097         sb.append(", annotation=").append(annotation);
098         sb.append(", annotationType=").append(annotationType);
099         sb.append('}');
100         return sb.toString();
101     }
102 
103     @Nonnull
104     public static <T> Key<T> of(@Nonnull Class<T> source) {
105         return new Key<>(source);
106     }
107 
108     @Nonnull
109     public static <T> Key<T> of(@Nonnull Class<T> source, @Nonnull Annotation annotation) {
110         return new Key<>(source, annotation);
111     }
112 
113     @Nonnull
114     public static <T> Key<T> of(@Nonnull Class<T> source, @Nonnull Class<? extends Annotation> annotationType) {
115         return new Key<>(source, annotationType);
116     }
117 
118     @Nonnull
119     public static <T> Key<T> of(@Nonnull Binding<T> binding) {
120         return binding.getClassifier() != null new Key<>(binding.getSource(), binding.getClassifier()) :
121             (binding.getClassifierType() != null new Key<>(binding.getSource(), binding.getClassifierType()) new Key<>(binding.getSource()));
122     }
123 }