View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.types;
19  
20  import java.util.Iterator;
21  
22  import org.apache.hadoop.classification.InterfaceAudience;
23  import org.apache.hadoop.classification.InterfaceStability;
24  import org.apache.hadoop.hbase.util.Order;
25  import org.apache.hadoop.hbase.util.PositionedByteRange;
26  
27  /**
28   * <p>
29   * {@code Struct} is a simple {@link DataType} for implementing "compound
30   * rowkey" and "compound qualifier" schema design strategies.
31   * </p>
32   * <h3>Encoding</h3>
33   * <p>
34   * {@code Struct} member values are encoded onto the target byte[] in the order
35   * in which they are declared. A {@code Struct} may be used as a member of
36   * another {@code Struct}. {@code Struct}s are not {@code nullable} but their
37   * component fields may be.
38   * </p>
39   * <h3>Sort Order</h3>
40   * <p>
41   * {@code Struct} instances sort according to the composite order of their
42   * fields, that is, left-to-right and depth-first. This can also be thought of
43   * as lexicographic comparison of concatenated members.
44   * </p>
45   * <p>
46   * {@link StructIterator} is provided as a convenience for consuming the
47   * sequence of values. Users may find it more appropriate to provide their own
48   * custom {@link DataType} for encoding application objects rather than using
49   * this {@code Object[]} implementation. Examples are provided in test.
50   * </p>
51   * @see StructIterator
52   * @see DataType#isNullable()
53   */
54  @InterfaceAudience.Public
55  @InterfaceStability.Evolving
56  public class Struct implements DataType<Object[]> {
57  
58    @SuppressWarnings("rawtypes")
59    protected final DataType[] fields;
60    protected final boolean isOrderPreserving;
61    protected final boolean isSkippable;
62  
63    /**
64     * Create a new {@code Struct} instance defined as the sequence of
65     * {@code HDataType}s in {@code memberTypes}.
66     * <p>
67     * A {@code Struct} is {@code orderPreserving} when all of its fields
68     * are {@code orderPreserving}. A {@code Struct} is {@code skippable} when
69     * all of its fields are {@code skippable}.
70     * </p>
71     */
72    @SuppressWarnings("rawtypes")
73    public Struct(DataType[] memberTypes) {
74      this.fields = memberTypes;
75      // a Struct is not orderPreserving when any of its fields are not.
76      boolean preservesOrder = true;
77      // a Struct is not skippable when any of its fields are not.
78      boolean skippable = true;
79      for (int i = 0; i < this.fields.length; i++) {
80        DataType dt = this.fields[i];
81        if (!dt.isOrderPreserving()) preservesOrder = false;
82        if (i < this.fields.length - 2 && !dt.isSkippable()) {
83          throw new IllegalArgumentException("Field in position " + i
84            + " is not skippable. Non-right-most struct fields must be skippable.");
85        }
86        if (!dt.isSkippable()) skippable = false;
87      }
88      this.isOrderPreserving = preservesOrder;
89      this.isSkippable = skippable;
90    }
91  
92    @Override
93    public boolean isOrderPreserving() { return isOrderPreserving; }
94  
95    @Override
96    public Order getOrder() { return null; }
97  
98    @Override
99    public boolean isNullable() { return false; }
100 
101   @Override
102   public boolean isSkippable() { return isSkippable; }
103 
104   @SuppressWarnings("unchecked")
105   @Override
106   public int encodedLength(Object[] val) {
107     assert fields.length == val.length;
108     int sum = 0;
109     for (int i = 0; i < fields.length; i++)
110       sum += fields[i].encodedLength(val[i]);
111     return sum;
112   }
113 
114   @Override
115   public Class<Object[]> encodedClass() { return Object[].class; }
116 
117   /**
118    * Retrieve an {@link Iterator} over the values encoded in {@code src}.
119    * {@code src}'s position is consumed by consuming this iterator.
120    */
121   public StructIterator iterator(PositionedByteRange src) {
122     return new StructIterator(src, fields);
123   }
124 
125   @Override
126   public int skip(PositionedByteRange src) {
127     StructIterator it = iterator(src);
128     int skipped = 0;
129     while (it.hasNext())
130       skipped += it.skip();
131     return skipped;
132   }
133 
134   @Override
135   public Object[] decode(PositionedByteRange src) {
136     int i = 0;
137     Object[] ret = new Object[fields.length];
138     Iterator<Object> it = iterator(src);
139     while (it.hasNext())
140       ret[i++] = it.next();
141     return ret;
142   }
143 
144   /**
145    * Read the field at {@code index}. {@code src}'s position is not affected.
146    */
147   public Object decode(PositionedByteRange src, int index) {
148     assert index >= 0;
149     StructIterator it = iterator(src.shallowCopy());
150     for (; index > 0; index--)
151       it.skip();
152     return it.next();
153   }
154 
155   @SuppressWarnings("unchecked")
156   @Override
157   public int encode(PositionedByteRange dst, Object[] val) {
158     assert fields.length == val.length;
159     int written = 0;
160     for (int i = 0; i < fields.length; i++) {
161       written += fields[i].encode(dst, val[i]);
162     }
163     return written;
164   }
165 }