View Javadoc

1   /*
2    *  Copyright 2001-2013 Stephen Colebourne
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  package org.joda.beans.impl.direct;
17  
18  import java.util.AbstractCollection;
19  import java.util.AbstractMap;
20  import java.util.AbstractSet;
21  import java.util.Arrays;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import org.joda.beans.MetaProperty;
28  
29  /**
30   * A map of name to meta-property designed for use by {@code DirectBean}.
31   * <p>
32   * This meta-property map implementation is designed primarily for code-generation.
33   * It stores a reference to the meta-bean and the meta-properties.
34   * The meta-properties are accessed using {@link DirectMetaBean#metaPropertyGet(String)}.
35   * <p>
36   * This class is immutable and thread-safe.
37   * 
38   * @author Stephen Colebourne
39   */
40  @SuppressWarnings("rawtypes")
41  public final class DirectMetaPropertyMap implements Map<String, MetaProperty<?>> {
42  
43      /** The meta-bean. */
44      private final DirectMetaBean metaBean;
45      /** The property names. */
46      private final Set<String> keys;
47      /** The meta-properties. */
48      private final Collection<MetaProperty<?>> values;
49      /** The map entries. */
50      private final Set<Entry<String, MetaProperty<?>>> entries;
51  
52      /**
53       * Constructor.
54       * 
55       * @param metaBean  the meta-bean, not null
56       * @param parent  the superclass parent, may be null
57       * @param propertyNames  the property names, not null
58       */
59      @SuppressWarnings("unchecked")
60      public DirectMetaPropertyMap(final DirectMetaBean metaBean, DirectMetaPropertyMap parent, String... propertyNames) {
61          if (metaBean == null) {
62              throw new NullPointerException("MetaBean must not be null");
63          }
64          this.metaBean = metaBean;
65          int parentSize = 0;
66          final Entry<String, MetaProperty<?>>[] metaProperties;
67          if (parent != null) {
68              parentSize = parent.size();
69              metaProperties = Arrays.copyOf(((Entries) parent.entries).metaProperties, parentSize + propertyNames.length);
70          } else {
71              metaProperties = new Entry[propertyNames.length];
72          }
73          for (int i = 0; i < propertyNames.length; i++) {
74              metaProperties[i + parentSize] = new AbstractMap.SimpleImmutableEntry(propertyNames[i], metaBean.metaPropertyGet(propertyNames[i]));
75          }
76          keys = new Keys(metaProperties);
77          values = new Values(metaProperties);
78          entries = new Entries(metaProperties);
79      }
80  
81      //-----------------------------------------------------------------------
82      @Override
83      public int size() {
84          return keys.size();
85      }
86  
87      @Override
88      public boolean isEmpty() {
89          return size() == 0;
90      }
91  
92      @SuppressWarnings("unchecked")
93      @Override
94      public MetaProperty<Object> get(Object propertyName) {
95          if (propertyName  instanceof String) {
96              return (MetaProperty<Object>) metaBean.metaPropertyGet((String) propertyName);
97          }
98          return null;
99      }
100 
101     @Override
102     public boolean containsKey(Object propertyName) {
103         return propertyName instanceof String &&
104                 metaBean.metaPropertyGet(propertyName.toString()) != null;
105     }
106 
107     @Override
108     public boolean containsValue(Object value) {
109         return value instanceof MetaProperty &&
110                 metaBean.metaPropertyGet(((MetaProperty<?>) value).name()) != null;
111     }
112 
113     //-----------------------------------------------------------------------
114     @Override
115     public MetaProperty<?> put(String key, MetaProperty<?> value) {
116         throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified");
117     }
118 
119     @Override
120     public MetaProperty<?> remove(Object key) {
121         throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified");
122     }
123 
124     @Override
125     public void putAll(Map<? extends String, ? extends MetaProperty<?>> m) {
126         throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified");
127     }
128 
129     @Override
130     public void clear() {
131         throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified");
132     }
133 
134     //-----------------------------------------------------------------------
135     @Override
136     public Set<String> keySet() {
137         return keys;
138     }
139 
140     @Override
141     public Collection<MetaProperty<?>> values() {
142         return values;
143     }
144 
145     @Override
146     public Set<Entry<String, MetaProperty<?>>> entrySet() {
147         return entries;
148     }
149 
150     //-----------------------------------------------------------------------
151     /**
152      * Collection implementation for the keys.
153      */
154     private static final class Keys extends AbstractSet<String> {
155         private final Entry<String, MetaProperty<?>>[] metaProperties;
156 
157         private Keys(Entry<String, MetaProperty<?>>[] metaProperties) {
158             this.metaProperties = metaProperties;
159         }
160 
161         @Override
162         public Iterator<String> iterator() {
163             return new Iterator<String>() {
164                 private int index;
165                 @Override
166                 public boolean hasNext() {
167                     return index < metaProperties.length;
168                 }
169                 @Override
170                 public String next() {
171                     return metaProperties[index++].getKey();
172                 }
173                 @Override
174                 public void remove() {
175                     throw new UnsupportedOperationException();
176                 }
177             };
178         }
179 
180         @Override
181         public int size() {
182             return metaProperties.length;
183         }
184     }
185 
186     /**
187      * Collection implementation for the values.
188      */
189     private static final class Values extends AbstractCollection<MetaProperty<?>> {
190         private final Entry<String, MetaProperty<?>>[] metaProperties;
191 
192         private Values(Entry<String, MetaProperty<?>>[] metaProperties) {
193             this.metaProperties = metaProperties;
194         }
195 
196         @Override
197         public Iterator<MetaProperty<?>> iterator() {
198             return new Iterator<MetaProperty<?>>() {
199                 private int index;
200                 @Override
201                 public boolean hasNext() {
202                     return index < metaProperties.length;
203                 }
204                 @Override
205                 public MetaProperty<?> next() {
206                     return metaProperties[index++].getValue();
207                 }
208                 @Override
209                 public void remove() {
210                     throw new UnsupportedOperationException();
211                 }
212             };
213         }
214 
215         @Override
216         public int size() {
217             return metaProperties.length;
218         }
219     }
220 
221     /**
222      * Collection implementation for the entries.
223      */
224     private static final class Entries extends AbstractSet<Entry<String, MetaProperty<?>>> {
225         private final Entry<String, MetaProperty<?>>[] metaProperties;
226 
227         private Entries(Entry<String, MetaProperty<?>>[] metaProperties) {
228             this.metaProperties = metaProperties;
229         }
230 
231         @Override
232         public Iterator<Entry<String, MetaProperty<?>>> iterator() {
233             return new Iterator<Entry<String, MetaProperty<?>>>() {
234                 private int index;
235                 @Override
236                 public boolean hasNext() {
237                     return index < metaProperties.length;
238                 }
239                 @Override
240                 public Entry<String, MetaProperty<?>> next() {
241                     return metaProperties[index++];
242                 }
243                 @Override
244                 public void remove() {
245                     throw new UnsupportedOperationException();
246                 }
247             };
248         }
249 
250         @Override
251         public int size() {
252             return metaProperties.length;
253         }
254     }
255 
256 }