001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  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 org.apache.hadoop.io;
019    
020    import java.io.DataInput;
021    import java.io.DataOutput;
022    import java.io.IOException;
023    import java.util.Collection;
024    import java.util.Comparator;
025    import java.util.Map;
026    import java.util.Set;
027    import java.util.SortedMap;
028    import java.util.TreeMap;
029    
030    import org.apache.hadoop.classification.InterfaceAudience;
031    import org.apache.hadoop.classification.InterfaceStability;
032    import org.apache.hadoop.util.ReflectionUtils;
033    
034    /**
035     * A Writable SortedMap.
036     */
037    @InterfaceAudience.Public
038    @InterfaceStability.Stable
039    public class SortedMapWritable extends AbstractMapWritable
040      implements SortedMap<WritableComparable, Writable> {
041      
042      private SortedMap<WritableComparable, Writable> instance;
043      
044      /** default constructor. */
045      public SortedMapWritable() {
046        super();
047        this.instance = new TreeMap<WritableComparable, Writable>();
048      }
049      
050      /**
051       * Copy constructor.
052       * 
053       * @param other the map to copy from
054       */
055      public SortedMapWritable(SortedMapWritable other) {
056        this();
057        copy(other);
058      }
059    
060      @Override
061      public Comparator<? super WritableComparable> comparator() {
062        // Returning null means we use the natural ordering of the keys
063        return null;
064      }
065    
066      @Override
067      public WritableComparable firstKey() {
068        return instance.firstKey();
069      }
070    
071      @Override
072      public SortedMap<WritableComparable, Writable>
073      headMap(WritableComparable toKey) {
074        
075        return instance.headMap(toKey);
076      }
077    
078      @Override
079      public WritableComparable lastKey() {
080        return instance.lastKey();
081      }
082    
083      @Override
084      public SortedMap<WritableComparable, Writable>
085      subMap(WritableComparable fromKey, WritableComparable toKey) {
086        
087        return instance.subMap(fromKey, toKey);
088      }
089    
090      @Override
091      public SortedMap<WritableComparable, Writable>
092      tailMap(WritableComparable fromKey) {
093        
094        return instance.tailMap(fromKey);
095      }
096    
097      @Override
098      public void clear() {
099        instance.clear();
100      }
101    
102      @Override
103      public boolean containsKey(Object key) {
104        return instance.containsKey(key);
105      }
106    
107      @Override
108      public boolean containsValue(Object value) {
109        return instance.containsValue(value);
110      }
111    
112      @Override
113      public Set<java.util.Map.Entry<WritableComparable, Writable>> entrySet() {
114        return instance.entrySet();
115      }
116    
117      @Override
118      public Writable get(Object key) {
119        return instance.get(key);
120      }
121    
122      @Override
123      public boolean isEmpty() {
124        return instance.isEmpty();
125      }
126    
127      @Override
128      public Set<WritableComparable> keySet() {
129        return instance.keySet();
130      }
131    
132      @Override
133      public Writable put(WritableComparable key, Writable value) {
134        addToMap(key.getClass());
135        addToMap(value.getClass());
136        return instance.put(key, value);
137      }
138    
139      @Override
140      public void putAll(Map<? extends WritableComparable, ? extends Writable> t) {
141        for (Map.Entry<? extends WritableComparable, ? extends Writable> e:
142          t.entrySet()) {
143          
144          put(e.getKey(), e.getValue());
145        }
146      }
147    
148      @Override
149      public Writable remove(Object key) {
150        return instance.remove(key);
151      }
152    
153      @Override
154      public int size() {
155        return instance.size();
156      }
157    
158      @Override
159      public Collection<Writable> values() {
160        return instance.values();
161      }
162    
163      @SuppressWarnings("unchecked")
164      @Override
165      public void readFields(DataInput in) throws IOException {
166        super.readFields(in);
167        
168        // Read the number of entries in the map
169        
170        int entries = in.readInt();
171        
172        // Then read each key/value pair
173        
174        for (int i = 0; i < entries; i++) {
175          WritableComparable key =
176            (WritableComparable) ReflectionUtils.newInstance(getClass(
177                in.readByte()), getConf());
178          
179          key.readFields(in);
180          
181          Writable value = (Writable) ReflectionUtils.newInstance(getClass(
182              in.readByte()), getConf());
183          
184          value.readFields(in);
185          instance.put(key, value);
186        }
187      }
188    
189      @Override
190      public void write(DataOutput out) throws IOException {
191        super.write(out);
192        
193        // Write out the number of entries in the map
194        
195        out.writeInt(instance.size());
196        
197        // Then write out each key/value pair
198        
199        for (Map.Entry<WritableComparable, Writable> e: instance.entrySet()) {
200          out.writeByte(getId(e.getKey().getClass()));
201          e.getKey().write(out);
202          out.writeByte(getId(e.getValue().getClass()));
203          e.getValue().write(out);
204        }
205      }
206    
207      @Override
208      public boolean equals(Object obj) {
209        if (this == obj) {
210          return true;
211        }
212    
213        if (obj instanceof SortedMapWritable) {
214          Map map = (Map) obj;
215          if (size() != map.size()) {
216            return false;
217          }
218    
219          return entrySet().equals(map.entrySet());
220        }
221    
222        return false;
223      }
224    
225      @Override
226      public int hashCode() {
227        return instance.hashCode();
228      }
229    }