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 = (Key) o;
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 }
|