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 */
018package org.apache.hadoop.io;
019
020import java.io.DataInput;
021import java.io.DataOutput;
022import java.io.IOException;
023import java.util.Collection;
024import java.util.Comparator;
025import java.util.Map;
026import java.util.Set;
027import java.util.SortedMap;
028import java.util.TreeMap;
029
030import org.apache.hadoop.classification.InterfaceAudience;
031import org.apache.hadoop.classification.InterfaceStability;
032import org.apache.hadoop.util.ReflectionUtils;
033
034/**
035 * A Writable SortedMap.
036 */
037@InterfaceAudience.Public
038@InterfaceStability.Stable
039public 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  /** {@inheritDoc} */
061  public Comparator<? super WritableComparable> comparator() {
062    // Returning null means we use the natural ordering of the keys
063    return null;
064  }
065
066  /** {@inheritDoc} */
067  public WritableComparable firstKey() {
068    return instance.firstKey();
069  }
070
071  /** {@inheritDoc} */
072  public SortedMap<WritableComparable, Writable>
073  headMap(WritableComparable toKey) {
074    
075    return instance.headMap(toKey);
076  }
077
078  /** {@inheritDoc} */
079  public WritableComparable lastKey() {
080    return instance.lastKey();
081  }
082
083  /** {@inheritDoc} */
084  public SortedMap<WritableComparable, Writable>
085  subMap(WritableComparable fromKey, WritableComparable toKey) {
086    
087    return instance.subMap(fromKey, toKey);
088  }
089
090  /** {@inheritDoc} */
091  public SortedMap<WritableComparable, Writable>
092  tailMap(WritableComparable fromKey) {
093    
094    return instance.tailMap(fromKey);
095  }
096
097  /** {@inheritDoc} */
098  public void clear() {
099    instance.clear();
100  }
101
102  /** {@inheritDoc} */
103  public boolean containsKey(Object key) {
104    return instance.containsKey(key);
105  }
106
107  /** {@inheritDoc} */
108  public boolean containsValue(Object value) {
109    return instance.containsValue(value);
110  }
111
112  /** {@inheritDoc} */
113  public Set<java.util.Map.Entry<WritableComparable, Writable>> entrySet() {
114    return instance.entrySet();
115  }
116
117  /** {@inheritDoc} */
118  public Writable get(Object key) {
119    return instance.get(key);
120  }
121
122  /** {@inheritDoc} */
123  public boolean isEmpty() {
124    return instance.isEmpty();
125  }
126
127  /** {@inheritDoc} */
128  public Set<WritableComparable> keySet() {
129    return instance.keySet();
130  }
131
132  /** {@inheritDoc} */
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  /** {@inheritDoc} */
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  /** {@inheritDoc} */
149  public Writable remove(Object key) {
150    return instance.remove(key);
151  }
152
153  /** {@inheritDoc} */
154  public int size() {
155    return instance.size();
156  }
157
158  /** {@inheritDoc} */
159  public Collection<Writable> values() {
160    return instance.values();
161  }
162
163  /** {@inheritDoc} */
164  @SuppressWarnings("unchecked")
165  @Override
166  public void readFields(DataInput in) throws IOException {
167    super.readFields(in);
168    
169    // Read the number of entries in the map
170    
171    int entries = in.readInt();
172    
173    // Then read each key/value pair
174    
175    for (int i = 0; i < entries; i++) {
176      WritableComparable key =
177        (WritableComparable) ReflectionUtils.newInstance(getClass(
178            in.readByte()), getConf());
179      
180      key.readFields(in);
181      
182      Writable value = (Writable) ReflectionUtils.newInstance(getClass(
183          in.readByte()), getConf());
184      
185      value.readFields(in);
186      instance.put(key, value);
187    }
188  }
189
190  /** {@inheritDoc} */
191  @Override
192  public void write(DataOutput out) throws IOException {
193    super.write(out);
194    
195    // Write out the number of entries in the map
196    
197    out.writeInt(instance.size());
198    
199    // Then write out each key/value pair
200    
201    for (Map.Entry<WritableComparable, Writable> e: instance.entrySet()) {
202      out.writeByte(getId(e.getKey().getClass()));
203      e.getKey().write(out);
204      out.writeByte(getId(e.getValue().getClass()));
205      e.getValue().write(out);
206    }
207  }
208
209  @Override
210  public boolean equals(Object obj) {
211    if (this == obj) {
212      return true;
213    }
214
215    if (obj instanceof SortedMapWritable) {
216      Map map = (Map) obj;
217      if (size() != map.size()) {
218        return false;
219      }
220
221      return entrySet().equals(map.entrySet());
222    }
223
224    return false;
225  }
226
227  @Override
228  public int hashCode() {
229    return instance.hashCode();
230  }
231}