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