/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed 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 com.linkedin.pinot.core.segment.index.readers; import com.linkedin.pinot.core.segment.index.ColumnMetadata; import com.linkedin.pinot.core.segment.memory.PinotDataBuffer; import java.nio.charset.Charset; import java.util.Arrays; public class StringDictionary extends ImmutableDictionaryReader { private final int lengthofMaxEntry; private static Charset UTF_8 = Charset.forName("UTF-8"); private final char paddingChar; public StringDictionary(PinotDataBuffer dataBuffer, ColumnMetadata metadata) { super(dataBuffer, metadata.getCardinality(), metadata.getStringColumnMaxLength()); lengthofMaxEntry = metadata.getStringColumnMaxLength(); paddingChar = metadata.getPaddingCharacter(); } @Override @SuppressWarnings("unchecked") public int indexOf(Object rawValue) { final String lookup = (String) rawValue; // This will always be a string byte[] lookupBytes = lookup.getBytes(UTF_8); if (lookupBytes.length >= lengthofMaxEntry) { // No need to pad the string return stringIndexOf(lookup); } // Need to pad the string before looking up byte[] dest = new byte[lengthofMaxEntry]; System.arraycopy(lookupBytes, 0, dest, 0, lookupBytes.length); Arrays.fill(dest, lookupBytes.length, dest.length, (byte) paddingChar); return stringIndexOf(new String(dest, UTF_8)); } @Override public String get(int dictionaryId) { if ((dictionaryId == -1) || (dictionaryId >= length())) { return "null"; } byte[] bytes = dataFileReader.getBytes(dictionaryId, 0); for (int i = lengthofMaxEntry - 1; i >= 0; i--) { if (bytes[i] != paddingChar) { return new String(bytes, 0, i + 1, UTF_8); } } return ""; } @Override public long getLongValue(int dictionaryId) { throw new RuntimeException("cannot converted string to long"); } @Override public double getDoubleValue(int dictionaryId) { throw new RuntimeException("cannot converted string to double"); } @Override public int getIntValue(int dictionaryId) { throw new RuntimeException("cannot converted string to int"); } @Override public float getFloatValue(int dictionaryId) { throw new RuntimeException("cannot converted string to float"); } @Override public String getStringValue(int dictionaryId) { return getString(dictionaryId); } @Override public void readIntValues(int[] dictionaryIds, int startPos, int limit, int[] outValues, int outStartPos) { throw new RuntimeException("Can not convert string to int"); } @Override public void readLongValues(int[] dictionaryIds, int startPos, int limit, long[] outValues, int outStartPos) { throw new RuntimeException("Can not convert string to long"); } @Override public void readFloatValues(int[] dictionaryIds, int startPos, int limit, float[] outValues, int outStartPos) { throw new RuntimeException("Can not convert string to float"); } @Override public void readDoubleValues(int[] dictionaryIds, int startPos, int limit, double[] outValues, int outStartPos) { throw new RuntimeException("Can not convert string to double"); } @Override public void readStringValues(int[] dictionaryIds, int startPos, int limit, String[] outValues, int outStartPos) { dataFileReader.readStringValues(dictionaryIds, 0/*column*/, startPos, limit, outValues, outStartPos); int outEndPos = outStartPos + limit; for (int i = outStartPos; i < outEndPos; i++) { String val = outValues[i]; byte[] bytes = val.getBytes(UTF_8); for (int j = 0; j < lengthofMaxEntry; j++) { if (bytes[j] == paddingChar) { outValues[i] = new String(bytes, 0, j, UTF_8); break; } } } } private String getString(int dictionaryId) { return dataFileReader.getString(dictionaryId, 0); } }