You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by sa...@apache.org on 2017/01/04 06:13:27 UTC

phoenix git commit: Implement one, two, and three byte qualifier encoding schemes

Repository: phoenix
Updated Branches:
  refs/heads/encodecolumns2 11c0c3b7b -> 5469fd4cb


Implement one, two, and three byte qualifier encoding schemes


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/5469fd4c
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/5469fd4c
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/5469fd4c

Branch: refs/heads/encodecolumns2
Commit: 5469fd4cb5bf5c9ee91941fab5658b575bc6baf4
Parents: 11c0c3b
Author: Samarth <sa...@salesforce.com>
Authored: Tue Jan 3 19:03:28 2017 -0800
Committer: Samarth <sa...@salesforce.com>
Committed: Tue Jan 3 19:03:28 2017 -0800

----------------------------------------------------------------------
 .../apache/phoenix/end2end/AlterTableIT.java    |   2 +-
 .../expression/ArrayColumnExpression.java       |   6 +-
 .../apache/phoenix/index/IndexMaintainer.java   |   4 +-
 .../phoenix/iterate/BaseResultIterators.java    |   4 +-
 .../apache/phoenix/query/QueryConstants.java    |   8 +-
 .../java/org/apache/phoenix/schema/PTable.java  | 151 ++++++++++++-------
 .../org/apache/phoenix/schema/PTableImpl.java   |  18 +--
 .../tuple/EncodedColumnQualiferCellsList.java   |   8 +-
 .../apache/phoenix/util/EncodedColumnsUtil.java |   4 +-
 .../EncodedColumnQualifierCellsListTest.java    |  44 +++---
 .../apache/phoenix/util/PhoenixRuntimeTest.java |   9 +-
 .../util/QualifierEncodingSchemeTest.java       | 129 ++++++++++++++++
 12 files changed, 275 insertions(+), 112 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
index 91e9964..c2fb031 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
@@ -2465,7 +2465,7 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
             stmt.setString(4, columnName);
             ResultSet rs = stmt.executeQuery();
             assertTrue(rs.next());
-            assertTrue(Bytes.equals(QualifierEncodingScheme.FOUR_BYTE_QUALIFIERS.getEncodedBytes(expectedValue), rs.getBytes(1)));
+            assertTrue(Bytes.equals(QualifierEncodingScheme.FOUR_BYTE_QUALIFIERS.encode(expectedValue), rs.getBytes(1)));
             assertFalse(rs.next());
         }
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayColumnExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayColumnExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayColumnExpression.java
index b693ded..e52f667 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayColumnExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayColumnExpression.java
@@ -61,7 +61,7 @@ public class ArrayColumnExpression extends KeyValueColumnExpression {
         super(column, cf, SINGLE_KEYVALUE_COLUMN_QUALIFIER_BYTES);
         Preconditions.checkNotNull(encodingScheme);
         Preconditions.checkArgument(encodingScheme != NON_ENCODED_QUALIFIERS);
-        this.positionInArray = encodingScheme.getDecodedValue(cq);
+        this.positionInArray = encodingScheme.decode(cq);
         this.encodingScheme = encodingScheme;
         setKeyValueExpression();
     }
@@ -71,7 +71,7 @@ public class ArrayColumnExpression extends KeyValueColumnExpression {
         Preconditions.checkNotNull(encodingScheme);
         Preconditions.checkArgument(encodingScheme != NON_ENCODED_QUALIFIERS);
         this.arrayColDisplayName = displayName;
-        this.positionInArray = encodingScheme.getDecodedValue(column.getColumnQualifierBytes());
+        this.positionInArray = encodingScheme.decode(column.getColumnQualifierBytes());
         this.encodingScheme = encodingScheme;
         setKeyValueExpression();
     }
@@ -151,7 +151,7 @@ public class ArrayColumnExpression extends KeyValueColumnExpression {
     }
     
     public byte[] getPositionInArray() {
-        return encodingScheme.getEncodedBytes(positionInArray);
+        return encodingScheme.encode(positionInArray);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java b/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
index f19af6c..bd8236c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
@@ -952,7 +952,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
                 int maxIndex = Integer.MIN_VALUE;
                 // find the max col qualifier
                 for (Pair<ColumnReference, ColumnReference> colRefPair : colRefPairs) {
-                    int qualifier = encodingScheme.getDecodedValue(colRefPair.getFirst().getQualifier());
+                    int qualifier = encodingScheme.decode(colRefPair.getFirst().getQualifier());
                     maxIndex = Math.max(maxIndex, qualifier);
                 }
                 byte[][] colValues = new byte[maxIndex+1][];
@@ -990,7 +990,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
                     expression.evaluate(new ValueGetterTuple(valueGetter), ptr);
                     byte[] value = ptr.copyBytesIfNecessary();
 					if (value != null) {
-						int indexArrayPos = encodingScheme.getDecodedValue(indexColRef.getQualifier());
+						int indexArrayPos = encodingScheme.decode(indexColRef.getQualifier());
                         colValues[indexArrayPos] = value;
                     }
                 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
index 3cca2de..7ece6df 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
@@ -274,7 +274,7 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
         for (Pair<byte[], byte[]> whereCol : context.getWhereConditionColumns()) {
             byte[] cq = whereCol.getSecond();
             if (cq != null) {
-                int qualifier = table.getEncodingScheme().getDecodedValue(cq);
+                int qualifier = table.getEncodingScheme().decode(cq);
                 determineQualifierRange(qualifier, minMaxQualifiers);
             }
         }
@@ -285,7 +285,7 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
             if (entry.getValue() != null) {
                 for (byte[] cq : entry.getValue()) {
                     if (cq != null) {
-                        int qualifier = table.getEncodingScheme().getDecodedValue(cq);
+                        int qualifier = table.getEncodingScheme().decode(cq);
                         determineQualifierRange(qualifier, minMaxQualifiers);
                     }
                 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
index 54d9c74..eee4a5f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
@@ -169,14 +169,14 @@ public interface QueryConstants {
     // get away with storing them in a single byte? We would need to make our encoding scheme
     // cognizant of the fact that all bytes may not be available making them interoperable.
     // In other words allow upper casting but not downcasting.
-    public static final byte[] VALUE_COLUMN_QUALIFIER = FOUR_BYTE_QUALIFIERS.getEncodedBytes(1);
+    public static final byte[] VALUE_COLUMN_QUALIFIER = FOUR_BYTE_QUALIFIERS.encode(1);
     
     public static final byte[] ARRAY_VALUE_COLUMN_FAMILY = RESERVED_COLUMN_FAMILY_BYTES;
-    public static final byte[] ARRAY_VALUE_COLUMN_QUALIFIER = FOUR_BYTE_QUALIFIERS.getEncodedBytes(2);
+    public static final byte[] ARRAY_VALUE_COLUMN_QUALIFIER = FOUR_BYTE_QUALIFIERS.encode(2);
     
     public final static PName SINGLE_COLUMN_NAME = PNameFactory.newNormalizedName("s");
     public final static PName SINGLE_COLUMN_FAMILY_NAME = PNameFactory.newNormalizedName("s");
-    public final static byte[] SINGLE_COLUMN = FOUR_BYTE_QUALIFIERS.getEncodedBytes(3);
+    public final static byte[] SINGLE_COLUMN = FOUR_BYTE_QUALIFIERS.encode(3);
     public final static byte[] SINGLE_COLUMN_FAMILY = RESERVED_COLUMN_FAMILY_BYTES;
 
     /** END Set of reserved column qualifiers **/
@@ -208,7 +208,7 @@ public interface QueryConstants {
     public static final ImmutableBytesPtr EMPTY_COLUMN_BYTES_PTR = new ImmutableBytesPtr(
             EMPTY_COLUMN_BYTES);
     public static final Integer ENCODED_EMPTY_COLUMN_NAME = 0;
-    public static final byte[] ENCODED_EMPTY_COLUMN_BYTES = FOUR_BYTE_QUALIFIERS.getEncodedBytes(ENCODED_EMPTY_COLUMN_NAME);
+    public static final byte[] ENCODED_EMPTY_COLUMN_BYTES = FOUR_BYTE_QUALIFIERS.encode(ENCODED_EMPTY_COLUMN_NAME);
     public static final ImmutableBytesPtr ENCODED_EMPTY_COLUMN_BYTES_PTR = new ImmutableBytesPtr(
             ENCODED_EMPTY_COLUMN_BYTES);
     public final static String EMPTY_COLUMN_VALUE = "x";

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
index 4c85e48..5e9608b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
@@ -33,6 +33,8 @@ import org.apache.phoenix.hbase.index.util.KeyValueBuilder;
 import org.apache.phoenix.index.IndexMaintainer;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 
+import com.google.common.annotations.VisibleForTesting;
+
 
 /**
  * Definition of a Phoenix table
@@ -193,49 +195,50 @@ public interface PTable extends PMetaDataEntity {
     public enum QualifierEncodingScheme implements QualifierEncoderDecoder {
         NON_ENCODED_QUALIFIERS((byte)0, null) {
             @Override
-            public byte[] getEncodedBytes(int value) {
+            public byte[] encode(int value) {
                 throw new UnsupportedOperationException();
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes) {
+            public int decode(byte[] bytes) {
                 throw new UnsupportedOperationException();
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes, int offset, int length) {
+            public int decode(byte[] bytes, int offset, int length) {
                 throw new UnsupportedOperationException();
             }
             
             @Override
-            public boolean isEncodeable() {
-                return true;
-            }
-            
-            @Override
             public String toString() {
                 return name();
             }
         },
         ONE_BYTE_QUALIFIERS((byte)1, 255) {
+            private final int c = Math.abs(Byte.MIN_VALUE);
+            
             @Override
-            public byte[] getEncodedBytes(int value) {
-                throw new UnsupportedOperationException();
+            public byte[] encode(int value) {
+                if (value < 0 || value > maxQualifier) {
+                    throw new QualifierOutOfRangeException(0, maxQualifier);
+                }
+                return new byte[]{(byte)(value - c)};
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes) {
-                throw new UnsupportedOperationException();
+            public int decode(byte[] bytes) {
+                if (bytes.length != 1) {
+                    throw new InvalidQualifierBytesException(1, bytes.length);
+                }
+                return bytes[0] + c;
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes, int offset, int length) {
-                throw new UnsupportedOperationException();
-            }
-            
-            @Override
-            public boolean isEncodeable() {
-                return true;
+            public int decode(byte[] bytes, int offset, int length) {
+                if (length != 1) {
+                    throw new InvalidQualifierBytesException(1, length);
+                }
+                return bytes[offset] + c;
             }
             
             @Override
@@ -244,24 +247,30 @@ public interface PTable extends PMetaDataEntity {
             }
         },
         TWO_BYTE_QUALIFIERS((byte)2, 65535) {
+            private final int c = Math.abs(Short.MIN_VALUE);
+            
             @Override
-            public byte[] getEncodedBytes(int value) {
-                throw new UnsupportedOperationException();
+            public byte[] encode(int value) {
+                if (value < 0 || value > maxQualifier) {
+                    throw new QualifierOutOfRangeException(0, maxQualifier);
+                }
+                return Bytes.toBytes((short)(value - c));
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes) {
-                throw new UnsupportedOperationException();
+            public int decode(byte[] bytes) {
+                if (bytes.length != 2) {
+                    throw new InvalidQualifierBytesException(2, bytes.length);
+                }
+                return Bytes.toShort(bytes) + c;
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes, int offset, int length) {
-                throw new UnsupportedOperationException();
-            }
-            
-            @Override
-            public boolean isEncodeable() {
-                return true;
+            public int decode(byte[] bytes, int offset, int length) {
+                if (length != 2) {
+                    throw new InvalidQualifierBytesException(2, length);
+                }
+                return Bytes.toShort(bytes, offset, length) + c;
             }
             
             @Override
@@ -271,23 +280,36 @@ public interface PTable extends PMetaDataEntity {
         },
         THREE_BYTE_QUALIFIERS((byte)3, 16777215) {
             @Override
-            public byte[] getEncodedBytes(int value) {
-                throw new UnsupportedOperationException();
+            public byte[] encode(int value) {
+                if (value < 0 || value > maxQualifier) {
+                    throw new QualifierOutOfRangeException(0, maxQualifier);
+                }
+                byte[] arr = Bytes.toBytes(value);
+                return new byte[]{arr[1], arr[2], arr[3]};
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes) {
-                throw new UnsupportedOperationException();
+            public int decode(byte[] bytes) {
+                if (bytes.length != 3) {
+                    throw new InvalidQualifierBytesException(2, bytes.length);
+                }
+                byte[] toReturn = new byte[4];
+                toReturn[1] = bytes[0];
+                toReturn[2] = bytes[1];
+                toReturn[3] = bytes[2];
+                return Bytes.toInt(toReturn);
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes, int offset, int length) {
-                throw new UnsupportedOperationException();
-            }
-            
-            @Override
-            public boolean isEncodeable() {
-                return true;
+            public int decode(byte[] bytes, int offset, int length) {
+                if (length != 3) {
+                    throw new InvalidQualifierBytesException(3, length);
+                }
+                byte[] toReturn = new byte[4];
+                toReturn[1] = bytes[offset];
+                toReturn[2] = bytes[offset + 1];
+                toReturn[3] = bytes[offset + 2];
+                return Bytes.toInt(toReturn);
             }
             
             @Override
@@ -297,33 +319,37 @@ public interface PTable extends PMetaDataEntity {
         },
         FOUR_BYTE_QUALIFIERS((byte)4, Integer.MAX_VALUE) {
             @Override
-            public byte[] getEncodedBytes(int value) {
+            public byte[] encode(int value) {
+                if (value < 0) {
+                    throw new QualifierOutOfRangeException(0, maxQualifier);
+                }
                 return Bytes.toBytes(value);
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes) {
+            public int decode(byte[] bytes) {
+                if (bytes.length != 4) {
+                    throw new InvalidQualifierBytesException(4, bytes.length);
+                }
                 return Bytes.toInt(bytes);
             }
 
             @Override
-            public int getDecodedValue(byte[] bytes, int offset, int length) {
+            public int decode(byte[] bytes, int offset, int length) {
+                if (length != 4) {
+                    throw new InvalidQualifierBytesException(4, length);
+                }
                 return Bytes.toInt(bytes, offset, length);
             }
             
             @Override
-            public boolean isEncodeable() {
-                return true;
-            }
-            
-            @Override
             public String toString() {
                 return name();
             }
         };
         
-        private final byte metadataValue;
-        private final Integer maxQualifier;
+        final byte metadataValue;
+        final Integer maxQualifier;
         
         public byte getSerializedMetadataValue() {
             return this.metadataValue;
@@ -336,6 +362,7 @@ public interface PTable extends PMetaDataEntity {
             return QualifierEncodingScheme.values()[serializedValue];
         }
         
+        @Override
         public Integer getMaxQualifier() {
             return maxQualifier;
         }
@@ -344,13 +371,27 @@ public interface PTable extends PMetaDataEntity {
             this.metadataValue = serializedMetadataValue;
             this.maxQualifier = maxQualifier;
         }
+        
+        @VisibleForTesting
+        public static class QualifierOutOfRangeException extends RuntimeException {
+            public QualifierOutOfRangeException(int minQualifier, int maxQualifier) {
+                super("Qualifier out of range (" + minQualifier + ", " + maxQualifier + ")"); 
+            }
+        }
+        
+        @VisibleForTesting
+        public static class InvalidQualifierBytesException extends RuntimeException {
+            public InvalidQualifierBytesException(int expectedLength, int actualLength) {
+                super("Invalid number of qualifier bytes. Expected length: " + expectedLength + ". Actual: " + actualLength);
+            }
+        }
     }
     
     interface QualifierEncoderDecoder {
-        byte[] getEncodedBytes(int value);
-        int getDecodedValue(byte[] bytes);
-        int getDecodedValue(byte[] bytes, int offset, int length);
-        boolean isEncodeable();
+        byte[] encode(int value);
+        int decode(byte[] bytes);
+        int decode(byte[] bytes, int offset, int length);
+        Integer getMaxQualifier();
     }
 
     long getTimeStamp();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index 8ae1988..e84e529 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -20,7 +20,6 @@ package org.apache.phoenix.schema;
 import static org.apache.phoenix.hbase.index.util.KeyValueBuilder.addQuietly;
 import static org.apache.phoenix.hbase.index.util.KeyValueBuilder.deleteQuietly;
 import static org.apache.phoenix.schema.SaltingUtil.SALTING_COLUMN;
-import static org.apache.phoenix.util.EncodedColumnsUtil.usesEncodedColumnNames;
 
 import java.io.IOException;
 import java.sql.DriverManager;
@@ -122,7 +121,7 @@ public class PTableImpl implements PTable {
     private Map<byte[], PColumnFamily> familyByBytes;
     private Map<String, PColumnFamily> familyByString;
     private ListMultimap<String, PColumn> columnsByName;
-    private ListMultimap<KVColumnFamilyQualifier, PColumn> kvColumnsByEncodedQualifiers;
+    private ListMultimap<KVColumnFamilyQualifier, PColumn> kvColumnsByQualifiers;
     private PName pkName;
     private Integer bucketNum;
     private RowKeySchema rowKeySchema;
@@ -482,7 +481,7 @@ public class PTableImpl implements PTable {
         PColumn[] allColumns;
         
         this.columnsByName = ArrayListMultimap.create(columns.size(), 1);
-        this.kvColumnsByEncodedQualifiers = ArrayListMultimap.<KVColumnFamilyQualifier, PColumn>create(columns.size(), 1);
+        this.kvColumnsByQualifiers = ArrayListMultimap.<KVColumnFamilyQualifier, PColumn>create(columns.size(), 1);
         int numPKColumns = 0;
         if (bucketNum != null) {
             // Add salt column to allColumns and pkColumns, but don't add to
@@ -495,7 +494,6 @@ public class PTableImpl implements PTable {
             allColumns = new PColumn[columns.size()];
             pkColumns = Lists.newArrayListWithExpectedSize(columns.size());
         }
-        boolean encodedColumnQualifiers = usesEncodedColumnNames(qualifierEncodingScheme);
         for (PColumn column : columns) {
             allColumns[column.getPosition()] = column;
             PName familyName = column.getFamilyName();
@@ -516,11 +514,11 @@ public class PTableImpl implements PTable {
             }
             byte[] cq = column.getColumnQualifierBytes();
             String cf = column.getFamilyName() != null ? column.getFamilyName().getString() : null;
-            if (cf != null && cq != null && encodedColumnQualifiers) {
+            if (cf != null && cq != null) {
                 KVColumnFamilyQualifier info = new KVColumnFamilyQualifier(cf, cq);
-                if (kvColumnsByEncodedQualifiers.put(info, column)) {
+                if (kvColumnsByQualifiers.put(info, column)) {
                     int count = 0;
-                    for (PColumn dupColumn : kvColumnsByEncodedQualifiers.get(info)) {
+                    for (PColumn dupColumn : kvColumnsByQualifiers.get(info)) {
                         if (Objects.equal(familyName, dupColumn.getFamilyName())) {
                             count++;
                             if (count > 1) {
@@ -836,7 +834,7 @@ public class PTableImpl implements PTable {
             return getPColumnForColumnName(columnName);
         } else {
             String family = (String)PVarchar.INSTANCE.toObject(cf);
-            List<PColumn> columns = kvColumnsByEncodedQualifiers.get(new KVColumnFamilyQualifier(family, cq));
+            List<PColumn> columns = kvColumnsByQualifiers.get(new KVColumnFamilyQualifier(family, cq));
             int size = columns.size();
             if (size == 0) {
                 //TODO: samarth should we have a column qualifier not found exception?
@@ -926,7 +924,7 @@ public class PTableImpl implements PTable {
                         Collection<PColumn> columns = family.getColumns();
                         int maxEncodedColumnQualifier = Integer.MIN_VALUE;
                         for (PColumn column : columns) {
-                            int qualifier = qualifierEncodingScheme.getDecodedValue(column.getColumnQualifierBytes());
+                            int qualifier = qualifierEncodingScheme.decode(column.getColumnQualifierBytes());
                             maxEncodedColumnQualifier = Math.max(maxEncodedColumnQualifier, qualifier);
                         }
                         Expression[] colValues = new Expression[maxEncodedColumnQualifier+1];
@@ -940,7 +938,7 @@ public class PTableImpl implements PTable {
                         colValues[0]=LiteralExpression.newConstant(QueryConstants.EMPTY_COLUMN_VALUE_BYTES);
                         for (PColumn column : columns) {
                         	if (columnToValueMap.containsKey(column)) {
-                        	    int qualifier = qualifierEncodingScheme.getDecodedValue(column.getColumnQualifierBytes());
+                        	    int qualifier = qualifierEncodingScheme.decode(column.getColumnQualifierBytes());
                         		colValues[qualifier] = new LiteralExpression(columnToValueMap.get(column));
                         	}
                         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
index dcafd84..484aacb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
@@ -133,7 +133,7 @@ public class EncodedColumnQualiferCellsList implements List<Cell> {
         if (e == null) {
             throw new NullPointerException();
         }
-        int columnQualifier = encodingScheme.getDecodedValue(e.getQualifierArray(), e.getQualifierOffset(), e.getQualifierLength());
+        int columnQualifier = encodingScheme.decode(e.getQualifierArray(), e.getQualifierOffset(), e.getQualifierLength());
                 
         checkQualifierRange(columnQualifier);
         int idx = getArrayIndex(columnQualifier);
@@ -233,7 +233,7 @@ public class EncodedColumnQualiferCellsList implements List<Cell> {
             ListIterator<Cell> listItr = this.listIterator();
             while (listItr.hasNext()) {
                 Cell cellInThis = listItr.next();
-                int qualifier = encodingScheme.getDecodedValue(cellInThis.getQualifierArray(),
+                int qualifier = encodingScheme.decode(cellInThis.getQualifierArray(),
                             cellInThis.getQualifierOffset(), cellInThis.getQualifierLength());
                 try {
                     Cell cellInParam = list.getCellForColumnQualifier(qualifier);
@@ -357,7 +357,7 @@ public class EncodedColumnQualiferCellsList implements List<Cell> {
     }
 
     public Cell getCellForColumnQualifier(byte[] qualifierBytes) {
-        int columnQualifier = encodingScheme.getDecodedValue(qualifierBytes);
+        int columnQualifier = encodingScheme.decode(qualifierBytes);
         return getCellForColumnQualifier(columnQualifier);
     }
     
@@ -517,7 +517,7 @@ public class EncodedColumnQualiferCellsList implements List<Cell> {
             if (lastRet == -1) {
                 throw new IllegalStateException();
             }
-            int columnQualifier = encodingScheme.getDecodedValue(e.getQualifierArray(), e.getQualifierOffset(), e.getQualifierLength());                    
+            int columnQualifier = encodingScheme.decode(e.getQualifierArray(), e.getQualifierOffset(), e.getQualifierLength());                    
             int idx = getArrayIndex(columnQualifier);
             if (idx != lastRet) {
                 throw new IllegalArgumentException("Cell " + e + " with column qualifier "

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/main/java/org/apache/phoenix/util/EncodedColumnsUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/EncodedColumnsUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/EncodedColumnsUtil.java
index 26ffe82..1726115 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/EncodedColumnsUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/EncodedColumnsUtil.java
@@ -131,7 +131,7 @@ public class EncodedColumnsUtil {
             if (!SchemaUtil.isPKColumn(column)) {
                 String colFamily = column.getFamilyName().getString();
                 Pair<Integer, Integer> minMaxQualifiers = toReturn.get(colFamily);
-                Integer encodedColumnQualifier = encodingScheme.getDecodedValue(column.getColumnQualifierBytes());
+                Integer encodedColumnQualifier = encodingScheme.decode(column.getColumnQualifierBytes());
                 if (minMaxQualifiers == null) {
                     minMaxQualifiers = new Pair<>(encodedColumnQualifier, encodedColumnQualifier);
                     toReturn.put(colFamily, minMaxQualifiers);
@@ -156,7 +156,7 @@ public class EncodedColumnsUtil {
         if (encodingScheme == NON_ENCODED_QUALIFIERS) {
             return Bytes.toBytes(columnName);
         } else if (numberBasedQualifier != null) {
-            return encodingScheme.getEncodedBytes(numberBasedQualifier);
+            return encodingScheme.encode(numberBasedQualifier);
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/test/java/org/apache/phoenix/query/EncodedColumnQualifierCellsListTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/EncodedColumnQualifierCellsListTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/EncodedColumnQualifierCellsListTest.java
index a25af78..bd70f84 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/EncodedColumnQualifierCellsListTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/EncodedColumnQualifierCellsListTest.java
@@ -122,7 +122,7 @@ public class EncodedColumnQualifierCellsListTest {
         for (Cell c : cells) {
             assertTrue(list.contains(c));
         }
-        assertFalse(list.contains(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(13))));
+        assertFalse(list.contains(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(13))));
     }
     
     @Test
@@ -154,7 +154,7 @@ public class EncodedColumnQualifierCellsListTest {
         assertEquals(5, list.size());
         assertTrue(list.remove(cells[3]));
         assertEquals(4, list.size());
-        assertFalse(list.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(13))));
+        assertFalse(list.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(13))));
         assertEquals(4, list.size());
     }
     
@@ -165,10 +165,10 @@ public class EncodedColumnQualifierCellsListTest {
         EncodedColumnQualiferCellsList list2 = new EncodedColumnQualiferCellsList(11, 16, FOUR_BYTE_QUALIFIERS);
         populateList(list2);
         assertTrue(list1.containsAll(list2));
-        list2.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(11)));
+        list2.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(11)));
         assertTrue(list1.containsAll(list2));
         assertFalse(list2.containsAll(list1));
-        list2.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(13)));
+        list2.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(13)));
         assertFalse(list1.containsAll(list2));
         assertFalse(list2.containsAll(list1));
         List<Cell> arrayList = new ArrayList<>();
@@ -218,7 +218,7 @@ public class EncodedColumnQualifierCellsListTest {
         populateList(list2);
         // retainAll won't be modifying the list1 since they both have the same elements equality wise
         assertFalse(list1.retainAll(list2));
-        list2.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(12)));
+        list2.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(12)));
         assertTrue(list1.retainAll(list2));
         assertEquals(list1.size(), list2.size());
         for (Cell c : list1) {
@@ -408,7 +408,7 @@ public class EncodedColumnQualifierCellsListTest {
             i++;
             try {
                 itr.next();
-                list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(0)));
+                list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(0)));
                 if (i == 2) {
                     fail("ConcurrentModificationException should have been thrown as the list is being modified while being iterated through");
                 }
@@ -426,7 +426,7 @@ public class EncodedColumnQualifierCellsListTest {
         populateList(list);
         ListIterator<Cell> itr = list.listIterator();
         itr.next();
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(0)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(0)));
         try {
             itr.next();
             fail("ConcurrentModificationException should have been thrown as the list was modified without using iterator");
@@ -440,7 +440,7 @@ public class EncodedColumnQualifierCellsListTest {
         itr.next();
         itr.remove();
         itr.next();
-        list.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(0)));
+        list.remove(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(0)));
         try {
             itr.next();
             fail("ConcurrentModificationException should have been thrown as the list was modified without using iterator");
@@ -451,28 +451,28 @@ public class EncodedColumnQualifierCellsListTest {
     
     private void populateListAndArray(List<Cell> list, Cell[] cells) {
         // add elements in reserved range
-        list.add(cells[0] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(0)));
-        list.add(cells[1] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(5)));
-        list.add(cells[2] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(10)));
+        list.add(cells[0] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(0)));
+        list.add(cells[1] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(5)));
+        list.add(cells[2] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(10)));
 
         // add elements in qualifier range
-        list.add(cells[6] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(16)));
-        list.add(cells[4] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(12)));
-        list.add(cells[5] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(14)));
-        list.add(cells[3] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(11)));
+        list.add(cells[6] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(16)));
+        list.add(cells[4] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(12)));
+        list.add(cells[5] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(14)));
+        list.add(cells[3] = KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(11)));
     }
 
     private void populateList(List<Cell> list) {
         // add elements in reserved range
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(0)));
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(5)));
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(10)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(0)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(5)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(10)));
 
         // add elements in qualifier range
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(16)));
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(12)));
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(14)));
-        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.getEncodedBytes(11)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(16)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(12)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(14)));
+        list.add(KeyValue.createFirstOnRow(row, cf, FOUR_BYTE_QUALIFIERS.encode(11)));
     }
     
     private class DelegateCell implements Cell {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
index 3ce9809..7b81c8d 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
@@ -48,6 +48,7 @@ import org.apache.phoenix.jdbc.PhoenixStatement;
 import org.apache.phoenix.query.BaseConnectionlessQueryTest;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTable.QualifierEncodingScheme;
 import org.apache.phoenix.schema.TableNotFoundException;
 import org.apache.phoenix.schema.types.PDataType;
 import org.junit.Test;
@@ -346,11 +347,5 @@ public class PhoenixRuntimeTest extends BaseConnectionlessQueryTest {
         // Even with a day of skew, we won't consider the ts a nanos timestamp
         assertEquals(skewedTs, PhoenixRuntime.getWallClockTimeFromCellTimeStamp(skewedTs));
     }
-    
-    public static void main(String args[]) throws Exception {
-        byte[] bytes = Bytes.toBytes(4294967295l);
-        long value = ByteBuffer.wrap(bytes)
-                .order(ByteOrder.LITTLE_ENDIAN).getInt() & 0xFFFFFFFFL;
-        System.out.print(value);
-    }
+
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/5469fd4c/phoenix-core/src/test/java/org/apache/phoenix/util/QualifierEncodingSchemeTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/QualifierEncodingSchemeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/QualifierEncodingSchemeTest.java
new file mode 100644
index 0000000..3dbc676
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/QualifierEncodingSchemeTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.util;
+
+import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.FOUR_BYTE_QUALIFIERS;
+import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.ONE_BYTE_QUALIFIERS;
+import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.THREE_BYTE_QUALIFIERS;
+import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.TWO_BYTE_QUALIFIERS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.apache.phoenix.schema.PTable.QualifierEncodingScheme.InvalidQualifierBytesException;
+import org.junit.Test;
+
+public class QualifierEncodingSchemeTest {
+    
+    @Test
+    public void testOneByteQualifierEncodeDecode() {
+        assertEquals(1, ONE_BYTE_QUALIFIERS.decode(ONE_BYTE_QUALIFIERS.encode(1)));
+        assertEquals(127, ONE_BYTE_QUALIFIERS.decode(ONE_BYTE_QUALIFIERS.encode(127)));
+        assertEquals(63, ONE_BYTE_QUALIFIERS.decode(ONE_BYTE_QUALIFIERS.encode(63)));
+        assertEquals(130, ONE_BYTE_QUALIFIERS.decode(ONE_BYTE_QUALIFIERS.encode(130)));
+        assertEquals(255, ONE_BYTE_QUALIFIERS.decode(ONE_BYTE_QUALIFIERS.encode(255)));
+        byte[] arr1 = ONE_BYTE_QUALIFIERS.encode(255);
+        byte[] arr2 = new byte[] {-128, arr1[0]};
+        assertEquals(255, ONE_BYTE_QUALIFIERS.decode(arr2, 1, 1));
+        try {
+            ONE_BYTE_QUALIFIERS.decode(arr2);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        try {
+            ONE_BYTE_QUALIFIERS.decode(arr2, 0, 2);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        
+    }
+    
+    @Test
+    public void testTwoByteQualifierEncodeDecode() {
+        assertEquals(1, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(1)));
+        assertEquals(127, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(127)));
+        assertEquals(63, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(63)));
+        assertEquals(130, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(130)));
+        assertEquals(128, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(128)));
+        assertEquals(129, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(129)));
+        assertEquals(32767, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(32767)));
+        assertEquals(32768, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(32768)));
+        assertEquals(65535, TWO_BYTE_QUALIFIERS.decode(TWO_BYTE_QUALIFIERS.encode(65535)));
+        byte[] arr1 = TWO_BYTE_QUALIFIERS.encode(65535);
+        byte[] arr2 = new byte[] {-128, arr1[0], arr1[1]};
+        assertEquals(65535, TWO_BYTE_QUALIFIERS.decode(arr2, 1, 2));
+        try {
+            TWO_BYTE_QUALIFIERS.decode(arr2);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        try {
+            TWO_BYTE_QUALIFIERS.decode(arr2, 0, 1);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        
+    }
+    
+    @Test
+    public void testThreeByteQualifierEncodeDecode() {
+        assertEquals(1, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(1)));
+        assertEquals(127, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(127)));
+        assertEquals(63, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(63)));
+        assertEquals(130, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(130)));
+        assertEquals(128, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(128)));
+        assertEquals(129, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(129)));
+        assertEquals(32767, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(32767)));
+        assertEquals(32768, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(32768)));
+        assertEquals(65535, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(65535)));
+        assertEquals(16777215, THREE_BYTE_QUALIFIERS.decode(THREE_BYTE_QUALIFIERS.encode(16777215)));
+        byte[] arr1 = THREE_BYTE_QUALIFIERS.encode(16777215);
+        byte[] arr2 = new byte[] {-128, arr1[0], arr1[1], arr1[2]};
+        assertEquals(16777215, THREE_BYTE_QUALIFIERS.decode(arr2, 1, 3));
+        try {
+            THREE_BYTE_QUALIFIERS.decode(arr2);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        try {
+            THREE_BYTE_QUALIFIERS.decode(arr2, 0, 2);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        
+    }
+    
+    @Test
+    public void testFourByteQualifierEncodeDecode() {
+        assertEquals(1, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(1)));
+        assertEquals(127, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(127)));
+        assertEquals(63, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(63)));
+        assertEquals(130, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(130)));
+        assertEquals(128, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(128)));
+        assertEquals(129, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(129)));
+        assertEquals(32767, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(32767)));
+        assertEquals(32768, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(32768)));
+        assertEquals(65535, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(65535)));
+        assertEquals(Integer.MAX_VALUE, FOUR_BYTE_QUALIFIERS.decode(FOUR_BYTE_QUALIFIERS.encode(Integer.MAX_VALUE)));
+        byte[] arr1 = FOUR_BYTE_QUALIFIERS.encode(Integer.MAX_VALUE);
+        byte[] arr2 = new byte[] {-128, arr1[0], arr1[1], arr1[2], arr1[3]};
+        assertEquals(Integer.MAX_VALUE, FOUR_BYTE_QUALIFIERS.decode(arr2, 1, 4));
+        try {
+            FOUR_BYTE_QUALIFIERS.decode(arr2);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+        try {
+            FOUR_BYTE_QUALIFIERS.decode(arr2, 0, 3);
+            fail();
+        } catch (InvalidQualifierBytesException expected) {}
+    }
+    
+}