blob: 51c81c9276be7c8f4ffa3cf0fdfc443acdfcdfaf [file] [log] [blame]
limpbizkit5fb9d922008-10-14 23:35:56 +00001/**
2 * Copyright (C) 2008 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.inject;
18
limpbizkit76c24b12008-12-25 04:32:41 +000019import com.google.inject.internal.BindingImpl;
limpbizkit5fb9d922008-10-14 23:35:56 +000020import com.google.inject.internal.Errors;
limpbizkiteb405132009-04-14 00:50:25 +000021import com.google.inject.internal.ImmutableList;
limpbizkit53664a72009-02-21 00:25:27 +000022import com.google.inject.internal.Lists;
23import com.google.inject.internal.Maps;
limpbizkit5fb9d922008-10-14 23:35:56 +000024import com.google.inject.internal.MatcherAndConverter;
limpbizkit53664a72009-02-21 00:25:27 +000025import static com.google.inject.internal.Preconditions.checkNotNull;
limpbizkitee792462009-04-08 23:48:49 +000026import com.google.inject.spi.TypeListenerBinding;
limpbizkit5fb9d922008-10-14 23:35:56 +000027import java.lang.annotation.Annotation;
limpbizkit03b81a62009-03-18 05:34:39 +000028import java.util.ArrayList;
limpbizkit76c24b12008-12-25 04:32:41 +000029import java.util.Collections;
limpbizkit5fb9d922008-10-14 23:35:56 +000030import java.util.List;
31import java.util.Map;
limpbizkit5fb9d922008-10-14 23:35:56 +000032
33/**
34 * @author jessewilson@google.com (Jesse Wilson)
35 */
36class InheritingState implements State {
37
limpbizkit5fb9d922008-10-14 23:35:56 +000038 private final State parent;
dhanji5c1ab7f2009-01-04 07:17:25 +000039
40 // Must be a linked hashmap in order to preserve order of bindings in Modules.
41 private final Map<Key<?>, Binding<?>> explicitBindingsMutable = Maps.newLinkedHashMap();
limpbizkit5fb9d922008-10-14 23:35:56 +000042 private final Map<Key<?>, Binding<?>> explicitBindings
43 = Collections.unmodifiableMap(explicitBindingsMutable);
44 private final Map<Class<? extends Annotation>, Scope> scopes = Maps.newHashMap();
45 private final List<MatcherAndConverter> converters = Lists.newArrayList();
limpbizkitbf0d8762009-02-19 09:06:22 +000046 /*if[AOP]*/
limpbizkit5fb9d922008-10-14 23:35:56 +000047 private final List<MethodAspect> methodAspects = Lists.newArrayList();
limpbizkitbf0d8762009-02-19 09:06:22 +000048 /*end[AOP]*/
limpbizkitee792462009-04-08 23:48:49 +000049 private final List<TypeListenerBinding> listenerBindings = Lists.newArrayList();
limpbizkit5fb9d922008-10-14 23:35:56 +000050 private final WeakKeySet blacklistedKeys = new WeakKeySet();
limpbizkita8dccb32008-11-11 22:41:56 +000051 private final Object lock;
limpbizkit5fb9d922008-10-14 23:35:56 +000052
53 InheritingState(State parent) {
54 this.parent = checkNotNull(parent, "parent");
limpbizkita8dccb32008-11-11 22:41:56 +000055 this.lock = (parent == State.NONE) ? this : parent.lock();
limpbizkit5fb9d922008-10-14 23:35:56 +000056 }
57
58 public State parent() {
59 return parent;
60 }
61
62 @SuppressWarnings("unchecked") // we only put in BindingImpls that match their key types
63 public <T> BindingImpl<T> getExplicitBinding(Key<T> key) {
64 Binding<?> binding = explicitBindings.get(key);
65 return binding != null ? (BindingImpl<T>) binding : parent.getExplicitBinding(key);
66 }
67
68 public Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel() {
69 return explicitBindings;
70 }
71
72 public void putBinding(Key<?> key, BindingImpl<?> binding) {
73 explicitBindingsMutable.put(key, binding);
74 }
75
76 public Scope getScope(Class<? extends Annotation> annotationType) {
77 Scope scope = scopes.get(annotationType);
78 return scope != null ? scope : parent.getScope(annotationType);
79 }
80
81 public void putAnnotation(Class<? extends Annotation> annotationType, Scope scope) {
82 scopes.put(annotationType, scope);
83 }
84
85 public Iterable<MatcherAndConverter> getConvertersThisLevel() {
86 return converters;
87 }
88
89 public void addConverter(MatcherAndConverter matcherAndConverter) {
90 converters.add(matcherAndConverter);
91 }
92
93 public MatcherAndConverter getConverter(
94 String stringValue, TypeLiteral<?> type, Errors errors, Object source) {
95 MatcherAndConverter matchingConverter = null;
96 for (State s = this; s != State.NONE; s = s.parent()) {
97 for (MatcherAndConverter converter : s.getConvertersThisLevel()) {
98 if (converter.getTypeMatcher().matches(type)) {
99 if (matchingConverter != null) {
100 errors.ambiguousTypeConversion(stringValue, source, type, matchingConverter, converter);
101 }
102 matchingConverter = converter;
103 }
104 }
105 }
106 return matchingConverter;
107 }
108
limpbizkitbf0d8762009-02-19 09:06:22 +0000109 /*if[AOP]*/
limpbizkit5fb9d922008-10-14 23:35:56 +0000110 public void addMethodAspect(MethodAspect methodAspect) {
111 methodAspects.add(methodAspect);
112 }
113
limpbizkiteb405132009-04-14 00:50:25 +0000114 public ImmutableList<MethodAspect> getMethodAspects() {
115 return new ImmutableList.Builder<MethodAspect>()
116 .addAll(parent.getMethodAspects())
117 .addAll(methodAspects)
118 .build();
limpbizkit5fb9d922008-10-14 23:35:56 +0000119 }
limpbizkitbf0d8762009-02-19 09:06:22 +0000120 /*end[AOP]*/
limpbizkit5fb9d922008-10-14 23:35:56 +0000121
limpbizkitee792462009-04-08 23:48:49 +0000122 public void addTypeListener(TypeListenerBinding listenerBinding) {
limpbizkit03b81a62009-03-18 05:34:39 +0000123 listenerBindings.add(listenerBinding);
124 }
125
limpbizkitee792462009-04-08 23:48:49 +0000126 public List<TypeListenerBinding> getTypeListenerBindings() {
127 List<TypeListenerBinding> parentBindings = parent.getTypeListenerBindings();
128 List<TypeListenerBinding> result
129 = new ArrayList<TypeListenerBinding>(parentBindings.size() + 1);
limpbizkit03b81a62009-03-18 05:34:39 +0000130 result.addAll(parentBindings);
131 result.addAll(listenerBindings);
132 return result;
133 }
134
limpbizkit5fb9d922008-10-14 23:35:56 +0000135 public void blacklist(Key<?> key) {
136 parent.blacklist(key);
137 blacklistedKeys.add(key);
138 }
139
140 public boolean isBlacklisted(Key<?> key) {
141 return blacklistedKeys.contains(key);
142 }
limpbizkita8dccb32008-11-11 22:41:56 +0000143
144 public Object lock() {
145 return lock;
146 }
limpbizkit5fb9d922008-10-14 23:35:56 +0000147}