/** * This software is licensed to you under the Apache License, Version 2.0 (the * "Apache License"). * * LinkedIn's contributions are made under the Apache License. If you contribute * to the Software, the contributions will be deemed to have been made under the * Apache License, unless you expressly indicate otherwise. Please do not make any * contributions that would be inconsistent with the Apache License. * * You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, this software * distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache * License for the specific language governing permissions and limitations for the * software governed under the Apache License. * * © 2012 LinkedIn Corp. All Rights Reserved. */ package com.senseidb.search.req; import com.alibaba.fastjson.JSON; import com.browseengine.bobo.api.*; import com.browseengine.bobo.facets.DefaultFacetHandlerInitializerParam; import com.browseengine.bobo.facets.FacetHandlerInitializerParam; import com.browseengine.bobo.mapred.MapReduceResult; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import com.linkedin.norbert.network.Serializer; import com.sensei.search.req.protobuf.SenseiProtos; import com.senseidb.search.req.mapred.SenseiMapReduce; import com.senseidb.search.req.mapred.functions.*; import com.senseidb.util.JSONUtil; import org.apache.log4j.Logger; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Fieldable; import org.apache.lucene.search.Explanation; import org.apache.lucene.search.SortField; import org.json.JSONException; import java.io.*; import java.util.*; public class SenseiRequestProtoSerializer implements Serializer<SenseiRequest, SenseiResult> { private final static Logger logger = Logger.getLogger(SenseiRequestProtoSerializer.class); @Override public String requestName() { return "SenseiRequestV2"; } @Override public String responseName() { return "SenseiResponseV2"; } @Override public SenseiRequest requestFromBytes(byte[] bytes) { SenseiProtos.SenseiProtoRequest senseiProtoRequest = null; try { senseiProtoRequest = SenseiProtos.SenseiProtoRequest.parseFrom(bytes); } catch (InvalidProtocolBufferException e) { throw new IllegalArgumentException("Could not parse"); } SenseiRequest senseiRequest = new SenseiRequest(); for (SenseiProtos.BrowseSelection selection : senseiProtoRequest.getSelectionList()) { senseiRequest.addSelection(convertBrowseSelection(selection)); } for (SenseiProtos.SortField sortField : senseiProtoRequest.getSortSpecList()) { senseiRequest.addSortField(convertSortField(sortField)); } senseiRequest.setFacetSpecs(convertFacetSpecs(senseiProtoRequest.getFacetSpecList())); if (senseiProtoRequest.hasSenseiQuery()) { String senseiQueryString = senseiProtoRequest.getSenseiQuery(); SenseiQuery senseiQuery = null; try { com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(senseiQueryString); senseiQuery = new SenseiJSONQuery(new JSONUtil.FastJSONObject(jsonObject)); } catch (Exception e) { senseiQuery = new SenseiQuery(senseiQueryString.getBytes(SenseiQuery.UTF_8_CHARSET)); } senseiRequest.setQuery(senseiQuery); } if (senseiProtoRequest.hasOffset()) senseiRequest.setOffset(senseiProtoRequest.getOffset()); if (senseiProtoRequest.hasCount()) senseiRequest.setCount(senseiProtoRequest.getCount()); if (senseiProtoRequest.hasFetchStoredFields()) senseiRequest.setFetchStoredFields(senseiProtoRequest.getFetchStoredFields()); if (senseiProtoRequest.hasFetchStoredValue()) senseiRequest.setFetchStoredValue(senseiProtoRequest.getFetchStoredValue()); if (senseiProtoRequest.hasFacetHandlerParam()) senseiRequest.setFacetHandlerInitParamMap(convertFacetParams(senseiProtoRequest.getFacetHandlerParam())); if (senseiProtoRequest.getPartitionsCount() > 0) senseiRequest.setPartitions(new HashSet<Integer>(senseiProtoRequest.getPartitionsList())); if (senseiProtoRequest.hasExplain()) senseiRequest.setShowExplanation(senseiProtoRequest.getExplain()); if (senseiProtoRequest.hasRouteParam()) senseiRequest.setRouteParam(senseiProtoRequest.getRouteParam()); if (senseiProtoRequest.getGroupByCount() > 0) { List<String> groupByList = senseiProtoRequest.getGroupByList(); senseiRequest.setGroupBy(groupByList.toArray(new String[]{})); } if (senseiProtoRequest.getDistinctCount() > 0) senseiRequest.setDistinct(senseiProtoRequest.getDistinctList().toArray(new String[]{})); if (senseiProtoRequest.hasMaxPerGroup()) senseiRequest.setMaxPerGroup(senseiProtoRequest.getMaxPerGroup()); if (senseiProtoRequest.getTermVectorsToFetchCount() > 0) { senseiRequest.setTermVectorsToFetch(new HashSet<String>(senseiProtoRequest.getTermVectorsToFetchList())); } if (senseiProtoRequest.getSelectListCount() > 0) { senseiRequest.setSelectList(senseiProtoRequest.getSelectListList()); } if (senseiProtoRequest.hasMapReduce()) { SenseiMapReduce mapReduceFunction = convertMapReduce(senseiProtoRequest.getMapReduce()); if (mapReduceFunction != null) { senseiRequest.setMapReduceFunction(mapReduceFunction); List<String> columns = senseiProtoRequest.getMapReduceColumnsList(); JSONUtil.FastJSONObject jsonObject = new JSONUtil.FastJSONObject(); try { jsonObject.put("column", columns.get(0)); jsonObject.put("columns", columns.toArray(new String[]{})); } catch (JSONException e) { throw new IllegalStateException(e); } senseiRequest.getMapReduceFunction().init(jsonObject); } else { ByteString mapReduceBytes = senseiProtoRequest.getMapReduceBytes(); Object object = null; try { ObjectInputStream ois = new ObjectInputStream(mapReduceBytes.newInput()); object = ois.readObject(); } catch (IOException ioException) { // Shouldn't happen. logger.error("IO Exception deserializing map reduce, ignoring mapreduce", ioException); } catch (ClassNotFoundException cnfe) { logger.error("Could not find class to deserialize to, ignoring mapreduce", cnfe); } if (object != null) { SenseiMapReduce mapReduce = (SenseiMapReduce) object; senseiRequest.setMapReduceFunction(mapReduce); } } } return senseiRequest; } @Override public byte[] requestToBytes(SenseiRequest request) { SenseiProtos.SenseiProtoRequest.Builder builder = SenseiProtos.SenseiProtoRequest.newBuilder(); if (request.getSelections() != null) { for (BrowseSelection browseSelection : request.getSelections()) { builder.addSelection(convertBrowseSelection(browseSelection)); } } for (SortField sortField : request.getSort()) { builder.addSortSpec(convertSortField(sortField)); } if (request.getFacetSpecs() != null) { for (Map.Entry<String, FacetSpec> facetSpec : request.getFacetSpecs().entrySet()) { builder.addFacetSpec(convertFacetSpec(facetSpec.getKey(), facetSpec.getValue())); } } if (request.getQuery() != null) { SenseiQuery senseiQuery = request.getQuery(); builder.setSenseiQuery(senseiQuery.toString()); } builder .setOffset(request.getOffset()) .setCount(request.getCount()) .setFetchStoredFields(request.isFetchStoredFields()) .setFetchStoredValue(request.isFetchStoredValue()) .setFacetHandlerParam(convertFacetParams(request.getFacetHandlerInitParamMap())) .addAllPartitions(request.getPartitions() == null ? Collections.<Integer>emptyList() : request.getPartitions()) .setExplain(request.isShowExplanation()) .setRouteParam(request.getRouteParam()) .setMaxPerGroup(request.getMaxPerGroup()); if (request.getGroupBy() != null) { builder.addAllGroupBy(Arrays.asList(request.getGroupBy())); } if(request.getDistinct() != null) { builder.addAllDistinct(Arrays.asList(request.getDistinct())); } if(request.getTermVectorsToFetch() != null) { builder.addAllTermVectorsToFetch(request.getTermVectorsToFetch()); } if(request.getSelectList() != null) { builder.addAllSelectList(request.getSelectList()); } if (request.getMapReduceFunction() != null) { SenseiProtos.SenseiMapReduceFunction protoMapReduceFunction = convertMapReduce(request.getMapReduceFunction()); builder.setMapReduce(protoMapReduceFunction); if (protoMapReduceFunction == SenseiProtos.SenseiMapReduceFunction.UNKNOWN) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(request.getMapReduceFunction()); oos.flush(); } catch (IOException e) { logger.error("Could not deserialize map reduce function", e); } builder.setMapReduceBytes(ByteString.copyFrom(baos.toByteArray())); } else { String[] columns = request.getMapReduceFunction().getColumns(); builder.addAllMapReduceColumns(Arrays.asList(columns)); } } SenseiProtos.SenseiProtoRequest senseiProtoRequest = builder.build(); return senseiProtoRequest.toByteArray(); } private SenseiProtos.JavaPrimitives getPrimitiveType(Object[] array) { if (array instanceof Integer[]) { return SenseiProtos.JavaPrimitives.INT; } else if (array instanceof Long[]) { return SenseiProtos.JavaPrimitives.LONG; } else if (array instanceof Byte[]) { return SenseiProtos.JavaPrimitives.BYTE; } else if (array instanceof Character[]) { return SenseiProtos.JavaPrimitives.CHAR; } else if (array instanceof Float[]) { return SenseiProtos.JavaPrimitives.FLOAT; } else if (array instanceof Double[]) { return SenseiProtos.JavaPrimitives.DOUBLE; } else if (array instanceof Integer[]) { return SenseiProtos.JavaPrimitives.INT; } else if (array instanceof Short[]) { return SenseiProtos.JavaPrimitives.SHORT; } else if (array instanceof String[]) { return SenseiProtos.JavaPrimitives.STRING; } else { // Try to figure if the individual elements in the array are primitive and homogenous int[] counts = new int[SenseiProtos.JavaPrimitives.values().length + 1]; for(Object o : array) { SenseiProtos.JavaPrimitives primitiveType = getPrimitiveType(o); counts[primitiveType.getNumber()]++; } int uniqueCount = 0; int primitiveIndex = 0; for(int i = 0; i < counts.length; i++) { int count = counts[i]; if(count > 0) { primitiveIndex = i; uniqueCount++; } } if(uniqueCount == 1) { return SenseiProtos.JavaPrimitives.valueOf(primitiveIndex); } else { return SenseiProtos.JavaPrimitives.OBJECT; } } } private SenseiProtos.JavaPrimitives getPrimitiveType(Object o) { if (o instanceof Integer) { return SenseiProtos.JavaPrimitives.INT; } else if (o instanceof Long) { return SenseiProtos.JavaPrimitives.LONG; } else if (o instanceof Byte) { return SenseiProtos.JavaPrimitives.BYTE; } else if (o instanceof Character) { return SenseiProtos.JavaPrimitives.CHAR; } else if (o instanceof Float) { return SenseiProtos.JavaPrimitives.FLOAT; } else if (o instanceof Double) { return SenseiProtos.JavaPrimitives.DOUBLE; } else if (o instanceof Short) { return SenseiProtos.JavaPrimitives.SHORT; } else if (o instanceof String) { return SenseiProtos.JavaPrimitives.STRING; } else { return SenseiProtos.JavaPrimitives.OBJECT; } } private Object[] convert(List<String> values, SenseiProtos.JavaPrimitives type) { switch (type) { case BOOLEAN: { Boolean[] result = new Boolean[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Boolean.parseBoolean(values.get(i)); return result; } case INT: { Integer[] result = new Integer[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Integer.parseInt(values.get(i)); return result; } case LONG: { Long[] result = new Long[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Long.parseLong(values.get(i)); return result; } case BYTE: { Byte[] result = new Byte[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Byte.parseByte(values.get(i)); return result; } case CHAR: { Character[] result = new Character[values.size()]; for (int i = 0; i < result.length; i++) { result[i] = values.get(i).charAt(0); } return result; } case FLOAT: { Float[] result = new Float[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Float.parseFloat(values.get(i)); return result; } case DOUBLE: { Double[] result = new Double[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Double.parseDouble(values.get(i)); return result; } case SHORT: { Short[] result = new Short[values.size()]; for (int i = 0; i < result.length; i++) result[i] = Short.parseShort(values.get(i)); return result; } case STRING: { String[] result = new String[values.size()]; for (int i = 0; i < result.length; i++) result[i] = values.get(i); return result; } default: { String error = "Unknown type for converting raw field values " + type; throw new IllegalArgumentException(error); } } } private Object convert(String value, SenseiProtos.JavaPrimitives type) { switch (type) { case BOOLEAN: return Boolean.parseBoolean(value); case INT: return Integer.parseInt(value); case LONG: return Long.parseLong(value); case BYTE: return Byte.parseByte(value); case CHAR: return value.charAt(0); case FLOAT: return Float.parseFloat(value); case DOUBLE: return Double.parseDouble(value); case SHORT: return Short.parseShort(value); case STRING: return value; default: { String error = "Unknown type for converting raw field values " + type; throw new IllegalArgumentException(error); } } } private SenseiProtos.Explanation convertExplanation(Explanation explanation) { SenseiProtos.Explanation.Builder builder = SenseiProtos.Explanation.newBuilder(); builder.setDescription(explanation.getDescription()); builder.setValue(explanation.getValue()); if (explanation.getDetails() != null && explanation.getDetails().length > 0) { for (int i = 0; i < explanation.getDetails().length; i++) { builder.addDetails(convertExplanation(explanation.getDetails()[i])); } } return builder.build(); } private Explanation convertExplanation(SenseiProtos.Explanation protoExplanation) { Explanation explanation = new Explanation(protoExplanation.getValue(), protoExplanation.getDescription()); if (protoExplanation.getDetailsCount() > 0) { for (SenseiProtos.Explanation detail : protoExplanation.getDetailsList()) { explanation.addDetail(convertExplanation(detail)); } } return explanation; } private SenseiProtos.Fieldable convertFieldable(Fieldable fieldable) { SenseiProtos.Fieldable.Builder builder = SenseiProtos.Fieldable.newBuilder(); builder.setBoost(fieldable.getBoost()); builder.setName(fieldable.name()); if (fieldable.stringValue() != null) builder.setStringValue(fieldable.stringValue()); builder.setStored(fieldable.isStored()); builder.setIndexed(fieldable.isIndexed()); builder.setTokenized(fieldable.isTokenized()); builder.setTermVectorStored(fieldable.isTermVectorStored()); builder.setStoreOffsetWithTermVector(fieldable.isStoreOffsetWithTermVector()); builder.setStorePositionWithTermVector(fieldable.isStorePositionWithTermVector()); builder.setBinary(fieldable.isBinary()); builder.setOmitNorms(fieldable.getOmitNorms()); builder.setLazy(fieldable.isLazy()); builder.setBinaryOffset(fieldable.getBinaryOffset()); builder.setBinaryLength(fieldable.getBinaryLength()); if (fieldable.getBinaryValue() != null) { builder.setBinaryValue(ByteString.copyFrom(fieldable.getBinaryValue())); } return builder.build(); } private Fieldable convertFieldable(SenseiProtos.Fieldable protoFieldable) { String name = protoFieldable.hasName() ? protoFieldable.getName() : null; String value = protoFieldable.hasStringValue() ? protoFieldable.getStringValue() : null; if (value != null) { Field.Store store = protoFieldable.hasStored() ? (protoFieldable.getStored() ? Field.Store.YES : Field.Store.NO) : Field.Store.NO; Field.TermVector termVector = Field.TermVector.toTermVector(protoFieldable.getStored(), protoFieldable.getStoreOffsetWithTermVector(), protoFieldable.getStorePositionWithTermVector()); Field.Index index = Field.Index.toIndex(protoFieldable.getIndexed(), false, protoFieldable.getOmitNorms()); Field field = new Field(name, value, store, index, termVector); if (protoFieldable.hasBoost()) field.setBoost(protoFieldable.getBoost()); if (protoFieldable.hasOmitNorms()) field.setOmitNorms(protoFieldable.getOmitNorms()); return field; } else { Field.Store store = protoFieldable.hasStored() ? (protoFieldable.getStored() ? Field.Store.YES : Field.Store.NO) : Field.Store.NO; byte[] binaryValue = protoFieldable.getBinaryValue() == null ? null : protoFieldable.getBinaryValue().toByteArray(); int binaryOffset = protoFieldable.getBinaryOffset(); int binaryLength = protoFieldable.getBinaryLength(); Field field = new Field(name, binaryValue, binaryOffset, binaryLength, store); return field; } } private SenseiProtos.Document convertDocument(Document document) { SenseiProtos.Document.Builder builder = SenseiProtos.Document.newBuilder(); builder.setBoost(document.getBoost()); if (document.getFields() != null) { for (Fieldable field : document.getFields()) { builder.addFields(convertFieldable(field)); } } return builder.build(); } private Document convertDocument(SenseiProtos.Document protoDocument) { Document document = new Document(); if (protoDocument.hasBoost()) document.setBoost(protoDocument.getBoost()); if (protoDocument.getFieldsCount() > 0) { for (SenseiProtos.Fieldable protoFieldable : protoDocument.getFieldsList()) { document.add(convertFieldable(protoFieldable)); } } return document; } private SenseiProtos.TermFrequencyMap convert(Map<String, BrowseHit.TermFrequencyVector> map) { SenseiProtos.TermFrequencyMap.Builder builder = SenseiProtos.TermFrequencyMap.newBuilder(); for(Map.Entry<String, BrowseHit.TermFrequencyVector> entry : map.entrySet()) { SenseiProtos.TermFrequencyVector.Builder vectorBuilder = SenseiProtos.TermFrequencyVector.newBuilder(); BrowseHit.TermFrequencyVector vector = entry.getValue(); for(int i = 0; i < vector.freqs.length; i++) { vectorBuilder.addFreq(vector.freqs[i]); vectorBuilder.addTerms(vector.terms[i]); } builder.addKey(entry.getKey()); builder.addValue(vectorBuilder); } return builder.build(); } private Map<String, BrowseHit.TermFrequencyVector> convert(SenseiProtos.TermFrequencyMap protoMap) { HashMap<String, BrowseHit.TermFrequencyVector> result = new HashMap<String, BrowseHit.TermFrequencyVector>(); for(int i = 0; i < protoMap.getKeyCount(); i++) { SenseiProtos.TermFrequencyVector protoVector = protoMap.getValue(i); int[] freq = new int[protoVector.getFreqCount()]; String[] terms = new String[protoVector.getTermsCount()]; for(int j = 0; j < protoVector.getFreqCount(); j++) { freq[j] = protoVector.getFreq(j); } for(int j = 0; j < protoVector.getTermsCount(); j++) { terms[j] = protoVector.getTerms(j); } BrowseHit.TermFrequencyVector termFrequencyVector = new BrowseHit.TermFrequencyVector(terms, freq); result.put(protoMap.getKey(i), termFrequencyVector); } return result; } private SenseiProtos.ObjectArray convert(Object[] objects) { SenseiProtos.ObjectArray.Builder builder = SenseiProtos.ObjectArray.newBuilder(); SenseiProtos.JavaPrimitives primitiveType = getPrimitiveType(objects); builder.setType(primitiveType); switch (primitiveType) { case BYTE: { for(Object o : objects) { builder.addIntValue((Byte) o); } break; } case SHORT: { for(Object o : objects) { builder.addIntValue((Short) o); } break; } case CHAR: { for(Object o : objects) { builder.addIntValue((Character) o); } break; } case INT: { for(Object o : objects) { builder.addIntValue((Integer) o); } break; } case BOOLEAN: { for(Object o : objects) { builder.addBooleanValue((Boolean) o); } break; } case LONG: { for(Object o : objects) { builder.addLongValue((Long) o); } break; } case FLOAT: { for(Object o : objects) { builder.addFloatValue((Float) o); } break; } case DOUBLE: { for(Object o : objects) { builder.addDoubleValue((Double) o); } break; } case STRING: { for(Object o : objects) { builder.addStringValue((String) o); } break; } case OBJECT: { for(Object o : objects) { if(o instanceof long[]) { SenseiProtos.LongArray.Builder longArrayBuilder = SenseiProtos.LongArray.newBuilder(); for(long item : (long[]) o) { longArrayBuilder.addItem(item); } builder.addLongArray(longArrayBuilder); } else { builder.addObjectValue(javaSerialize(o)); } } break; } } return builder.build(); } private Object[] convert(SenseiProtos.ObjectArray objectArray) { SenseiProtos.JavaPrimitives type = objectArray.getType(); switch (type) { case BOOLEAN: { Boolean[] result = new Boolean[objectArray.getBooleanValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = objectArray.getBooleanValue(i); } return result; } case BYTE: { Byte[] result = new Byte[objectArray.getIntValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = (byte) objectArray.getIntValue(i); } return result; } case CHAR: { Character[] result = new Character[objectArray.getIntValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = (char) objectArray.getIntValue(i); } return result; } case SHORT: { Short[] result = new Short[objectArray.getIntValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = (short) objectArray.getIntValue(i); } return result; } case INT: { Integer[] result = new Integer[objectArray.getIntValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = objectArray.getIntValue(i); } return result; } case LONG: { Long[] result = new Long[objectArray.getLongValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = objectArray.getLongValue(i); } return result; } case FLOAT: { Float[] result = new Float[objectArray.getFloatValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = objectArray.getFloatValue(i); } return result; } case DOUBLE: { Double[] result = new Double[objectArray.getDoubleValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = objectArray.getDoubleValue(i); } return result; } case STRING: { String[] result = new String[objectArray.getStringValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = objectArray.getStringValue(i); } return result; } case OBJECT: { if(objectArray.getLongArrayCount() > 0) { long[][] result = new long[objectArray.getLongArrayCount()][]; for(int i = 0; i < result.length; i++) { result[i] = new long[objectArray.getLongArray(i).getItemCount()]; for(int j = 0; j < result[i].length; j++) { result[i][j] = objectArray.getLongArray(i).getItem(j); } } return result; } else { Object[] result = new Object[objectArray.getObjectValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = javaDeserialize(objectArray.getObjectValue(i)); } return result; } } default: { Object[] result = new Object[objectArray.getObjectValueCount()]; for(int i = 0; i < result.length; i++) { result[i] = javaDeserialize(objectArray.getObjectValue(i)); } return result; } } } private SenseiProtos.SenseiHit convert(SenseiHit senseiHit) { SenseiProtos.SenseiHit.Builder builder = SenseiProtos.SenseiHit.newBuilder(); builder.setScore(senseiHit.getScore()); builder.setDocId(senseiHit.getDocid()); if(senseiHit.getFeatures() != null) { for (float f : senseiHit.getFeatures()) { builder.addFeatures(f); } } if(senseiHit.getRawFieldValues() != null) { SenseiProtos.FieldValues.Builder fieldValues = SenseiProtos.FieldValues.newBuilder(); for(Map.Entry<String, Object[]> entry : senseiHit.getRawFieldValues().entrySet()) { fieldValues.addKey(entry.getKey()); fieldValues.addRawValue(convert(entry.getValue())); String[] fields = senseiHit.getFields(entry.getKey()); fieldValues.addValue(convert(fields)); } builder.setFieldValues(fieldValues); } builder.setGroupPosition(senseiHit.getGroupPosition()); if (senseiHit.getGroupField() != null) builder.setGroupField(senseiHit.getGroupField()); if (senseiHit.getGroupValue() != null) { builder.setGroupValue(senseiHit.getGroupValue()); } if(senseiHit.getRawGroupValue() != null) { builder.setRawGroupValue(javaSerialize(senseiHit.getRawGroupValue())); } builder.setTotalGroupHitCount(senseiHit.getGroupHitsCount()); if (senseiHit.getGroupHits() != null && senseiHit.getSenseiGroupHits().length > 0) { for (BrowseHit groupHit : senseiHit.getSenseiGroupHits()) { if(groupHit instanceof SenseiHit) { SenseiProtos.SenseiHit protoGroupHit = convert((SenseiHit) groupHit); builder.addGroupHit(protoGroupHit); } else { throw new IllegalArgumentException("Expect the browse hits to be of type SenseiHit"); } } } if (senseiHit.getExplanation() != null) { builder.setExplanation(convertExplanation(senseiHit.getExplanation())); } builder.setUid(senseiHit.getUID()); if (senseiHit.getSrcData() != null) { builder.setSrcData(senseiHit.getSrcData()); } if (senseiHit.getStoredFields() != null) { builder.setStoredFields(convertDocument(senseiHit.getStoredFields())); } if (senseiHit.getStoredValue() != null) builder.setStoredValue(ByteString.copyFrom(senseiHit.getStoredValue())); if(senseiHit.getTermFreqMap() != null) { builder.setTermFrequencyMap(convert(senseiHit.getTermFreqMap())); } // builder.setSenseiHitBytes(javaSerialize(senseiHit)); return builder.build(); } private String[] convert(SenseiProtos.StringArray protoStringArray) { String[] result = new String[protoStringArray.getItemCount()]; for(int i = 0; i < result.length; i++) { result[i] = protoStringArray.getItem(i); } return result; } private SenseiProtos.StringArray convert(String[] stringArray) { SenseiProtos.StringArray.Builder builder = SenseiProtos.StringArray.newBuilder(); for(String string : stringArray) { builder.addItem(string); } return builder.build(); } private SenseiHit convert(SenseiProtos.SenseiHit protoSenseiHit) { SenseiHit senseiHit = new SenseiHit(); if (protoSenseiHit.hasScore()) { senseiHit.setScore(protoSenseiHit.getScore()); } if (protoSenseiHit.hasDocId()) { senseiHit.setDocid(protoSenseiHit.getDocId()); } SenseiProtos.FieldValues protoFieldValues = protoSenseiHit.getFieldValues(); Map<String, Object[]> rawFieldValues = new LinkedHashMap<String, Object[]>(); Map<String, String[]> fieldValues = new LinkedHashMap<String, String[]>(); if(protoFieldValues != null) { int numItems = protoFieldValues.getKeyCount(); if(numItems > 0) { for(int i = 0; i < numItems; i++) { String key = protoFieldValues.getKey(i); SenseiProtos.ObjectArray protoObjectArray = protoFieldValues.getRawValue(i); Object[] objects = convert(protoObjectArray); rawFieldValues.put(key, objects); fieldValues.put(key, convert(protoFieldValues.getValue(i))); } } } senseiHit.setRawFieldValues(rawFieldValues); senseiHit.setFieldValues(fieldValues); if (protoSenseiHit.hasGroupPosition()) { senseiHit.setGroupPosition(protoSenseiHit.getGroupPosition()); } if (protoSenseiHit.hasGroupField()) { senseiHit.setGroupField(protoSenseiHit.getGroupField()); } if (protoSenseiHit.hasGroupValue()) { senseiHit.setGroupValue(protoSenseiHit.getGroupValue()); } if(protoSenseiHit.hasRawGroupValue()) { senseiHit.setRawGroupValue(javaDeserialize(protoSenseiHit.getRawGroupValue())); } if(protoSenseiHit.hasTotalGroupHitCount()) { senseiHit.setGroupHitsCount(protoSenseiHit.getTotalGroupHitCount()); } if (protoSenseiHit.getGroupHitCount() > 0) { SenseiHit[] groupHits = new SenseiHit[protoSenseiHit.getGroupHitCount()]; int i = 0; for (SenseiProtos.SenseiHit hit : protoSenseiHit.getGroupHitList()) { groupHits[i++] = convert(hit); } senseiHit.setGroupHits(groupHits); } if (protoSenseiHit.hasExplanation()) { senseiHit.setExplanation(convertExplanation(protoSenseiHit.getExplanation())); } if (protoSenseiHit.hasUid()) { senseiHit.setUID(protoSenseiHit.getUid()); } if (protoSenseiHit.hasSrcData()) { senseiHit.setSrcData(protoSenseiHit.getSrcData()); } if (protoSenseiHit.hasStoredFields()) { senseiHit.setStoredFields(convertDocument(protoSenseiHit.getStoredFields())); } if (protoSenseiHit.hasStoredValue()) { senseiHit.setStoredValue(protoSenseiHit.getStoredValue().toByteArray()); } if (protoSenseiHit.hasTermFrequencyMap()) { senseiHit.setTermFreqMap(convert(protoSenseiHit.getTermFrequencyMap())); } if (protoSenseiHit.getFeaturesList() != null) { float [] features = new float[protoSenseiHit.getFeaturesCount()]; for (int i = 0; i < features.length; i++) { features[i] = protoSenseiHit.getFeatures(i); } senseiHit.setFeatures(features); } return senseiHit; } private BrowseFacet convertBrowseFacet(SenseiProtos.BrowseFacet protoFacet) { BrowseFacet facet = new BrowseFacet(); facet.setFacetValueHitCount(protoFacet.getHitCount()); if (protoFacet.hasValue()) facet.setValue(protoFacet.getValue()); return facet; } private SenseiProtos.BrowseFacet convertBrowseFacet(BrowseFacet browseFacet) { SenseiProtos.BrowseFacet.Builder builder = SenseiProtos.BrowseFacet.newBuilder(); builder.setHitCount(browseFacet.getFacetValueHitCount()); if (browseFacet.getValue() != null) builder.setValue(browseFacet.getValue()); return builder.build(); } private SenseiProtos.FacetAccessible convertFacetAccessible(FacetAccessible facetAccessible) { SenseiProtos.FacetAccessible.Builder builder = SenseiProtos.FacetAccessible.newBuilder(); // ByteString byteString = javaSerialize(facetAccessible); // builder.setFacetAccessibleBytes(byteString); List<BrowseFacet> facets = facetAccessible.getFacets(); for (BrowseFacet facet : facets) { SenseiProtos.BrowseFacet protoFacet = convertBrowseFacet(facet); builder.addFacets(protoFacet); } return builder.build(); } private FacetAccessible convertFacetAccessible(SenseiProtos.FacetAccessible facetAccessible) { // ByteString facetAccessibleBytes = facetAccessible.getFacetAccessibleBytes(); // return (FacetAccessible) javaDeserialize(facetAccessibleBytes); List<SenseiProtos.BrowseFacet> protoFacets = facetAccessible.getFacetsList(); BrowseFacet[] facets = new BrowseFacet[protoFacets.size()]; int i = 0; for (SenseiProtos.BrowseFacet protoFacet : protoFacets) { BrowseFacet browseFacet = convertBrowseFacet(protoFacet); facets[i++] = browseFacet; } return new MappedFacetAccessible(facets); } private SenseiProtos.FacetMap convertFacetMap(Map<String, FacetAccessible> facetMap) { SenseiProtos.FacetMap.Builder builder = SenseiProtos.FacetMap.newBuilder(); for (Map.Entry<String, FacetAccessible> entry : facetMap.entrySet()) { builder.addKey(entry.getKey()); builder.addValue(convertFacetAccessible(entry.getValue())); } return builder.build(); } private Map<String, FacetAccessible> convertFacetMap(SenseiProtos.FacetMap protoFacetMap) { Map<String, FacetAccessible> facetMap = new HashMap<String, FacetAccessible>(); for (int i = 0; i < protoFacetMap.getKeyCount(); i++) { facetMap.put(protoFacetMap.getKey(i), convertFacetAccessible(protoFacetMap.getValue(i))); } return facetMap; } private static final ByteString javaSerialize(Object o) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos); objectOutputStream.writeObject(o); objectOutputStream.close(); } catch (IOException ioException) { logger.error("Could not serialize java object ", ioException); } return ByteString.copyFrom(baos.toByteArray()); } private static final Object javaDeserialize(ByteString bytes) { ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray()); Object object = null; try { ObjectInputStream objectInputStream = new ObjectInputStream(bais); object = objectInputStream.readObject(); } catch (IOException ioException) { logger.error("Could not deserialize reduce result ", ioException); } catch (ClassNotFoundException cnfe) { logger.error("Unknown class trying to deserialize reduce result ", cnfe); } return object; } private SenseiProtos.MapReduceResult convertMapReduceResult(MapReduceResult mapReduceResult) { SenseiProtos.MapReduceResult.Builder builder = SenseiProtos.MapReduceResult.newBuilder(); List mapResults = mapReduceResult.getMapResults(); Serializable reduceResult = mapReduceResult.getReduceResult(); if (reduceResult != null) { builder.setReduceResult(javaSerialize(reduceResult)); } if (mapResults != null) { for (Object mapResult : mapResults) { builder.addMapResult(javaSerialize(mapResult)); } } return builder.build(); } private MapReduceResult convertMapReduceResult(SenseiProtos.MapReduceResult protoMapReduceResult) { MapReduceResult mapReduceResult = new MapReduceResult(); if (protoMapReduceResult.hasReduceResult()) { Object reduceResult = javaDeserialize(protoMapReduceResult.getReduceResult()); if (reduceResult != null) mapReduceResult.setReduceResult((Serializable) reduceResult); } if (protoMapReduceResult.getMapResultCount() > 0) { List mapResults = new ArrayList(); for (ByteString protoMapResult : protoMapReduceResult.getMapResultList()) { Object mapResult = javaDeserialize(protoMapResult); if (mapResult != null) mapResults.add(mapResult); } mapReduceResult.setMapResults(mapResults); } return mapReduceResult; } private SenseiProtos.ErrorType convert(ErrorType errorType) { switch (errorType) { case BoboExecutionError: return SenseiProtos.ErrorType.BoboExecutionError; case BQLParsingError: return SenseiProtos.ErrorType.BQLParsingError; case BrokerGatherError: return SenseiProtos.ErrorType.BrokerGatherError; case BrokerTimeout: return SenseiProtos.ErrorType.BrokerTimeout; case ExecutionTimeout: return SenseiProtos.ErrorType.ExecutionTimeout; case FederatedBrokerUnavailable: return SenseiProtos.ErrorType.FederatedBrokerUnavailable; case InternalError: return SenseiProtos.ErrorType.InternalError; case JsonCompilationError: return SenseiProtos.ErrorType.JsonCompilationError; case JsonParsingError: return SenseiProtos.ErrorType.JsonParsingError; case MergePartitionError: return SenseiProtos.ErrorType.MergePartitionError; case PartitionCallError: return SenseiProtos.ErrorType.PartitionCallError; case UnknownError: return SenseiProtos.ErrorType.UnknownError; default: { logger.warn("Unknown error type in proto serialization, setting unknown " + errorType); return SenseiProtos.ErrorType.UnknownError; } } } private ErrorType convert(SenseiProtos.ErrorType protoErrorType) { switch (protoErrorType) { case BoboExecutionError: return ErrorType.BoboExecutionError; case BQLParsingError: return ErrorType.BQLParsingError; case BrokerGatherError: return ErrorType.BrokerGatherError; case BrokerTimeout: return ErrorType.BrokerTimeout; case ExecutionTimeout: return ErrorType.ExecutionTimeout; case FederatedBrokerUnavailable: return ErrorType.FederatedBrokerUnavailable; case InternalError: return ErrorType.InternalError; case JsonCompilationError: return ErrorType.JsonCompilationError; case JsonParsingError: return ErrorType.JsonParsingError; case MergePartitionError: return ErrorType.MergePartitionError; case PartitionCallError: return ErrorType.PartitionCallError; case UnknownError: return ErrorType.UnknownError; default: { logger.warn("Unknown serialization error coming from protobuf, setting unknown " + protoErrorType); return ErrorType.UnknownError; } } } private SenseiProtos.SenseiError convert(SenseiError senseiError) { SenseiProtos.SenseiError.Builder builder = SenseiProtos.SenseiError.newBuilder(); builder.setCode(senseiError.getErrorCode()); if(senseiError.getMessage() != null) { builder.setMessage(senseiError.getMessage()); } if(senseiError.getErrorType() != null) { builder.setType(convert(senseiError.getErrorType())); } return builder.build(); } private SenseiError convert(SenseiProtos.SenseiError protoSenseiError) { String message = protoSenseiError.hasMessage() ? protoSenseiError.getMessage() : null; ErrorType errorType = protoSenseiError.hasType() ? convert(protoSenseiError.getType()) : null; int code = protoSenseiError.hasCode() ? protoSenseiError.getCode() : (errorType != null ? errorType.getDefaultErrorCode() : 0); SenseiError senseiError = new SenseiError(message, errorType, code); return senseiError; } @Override public byte[] responseToBytes(SenseiResult senseiResult) { SenseiProtos.SenseiProtoResult.Builder builder = SenseiProtos.SenseiProtoResult.newBuilder(); if (senseiResult.getParsedQuery() != null) builder.setParsedQuery(senseiResult.getParsedQuery()); if (senseiResult.getSenseiHits() != null && senseiResult.getSenseiHits().length > 0) { for (SenseiHit senseiHit : senseiResult.getSenseiHits()) { builder.addHit(convert(senseiHit)); } } builder.setTid(senseiResult.getTid()); builder.setNumHits(senseiResult.getNumHits()); builder.setTotalDocs(senseiResult.getTotalDocs()); FacetAccessible[] groupAccessibles = senseiResult.getGroupAccessibles(); if (groupAccessibles != null && groupAccessibles.length > 0) { for (FacetAccessible groupAccessible : groupAccessibles) { builder.addGroupAccessible(convertFacetAccessible(groupAccessible)); } } Map<String, FacetAccessible> facetMap = senseiResult.getFacetMap(); if (facetMap != null) { builder.setFacetMap(convertFacetMap(facetMap)); } builder.setTime(senseiResult.getTime()); if (senseiResult.getMapReduceResult() != null) builder.setMapReduceResult(convertMapReduceResult(senseiResult.getMapReduceResult())); if(senseiResult.getErrors() != null && !senseiResult.getErrors().isEmpty()) { for(SenseiError senseiError : senseiResult.getErrors()) { builder.addError(convert(senseiError)); } } SenseiProtos.SenseiProtoResult protoResult = builder.build(); return protoResult.toByteArray(); } @Override public SenseiResult responseFromBytes(byte[] bytes) { SenseiProtos.SenseiProtoResult senseiProtoResult = null; try { senseiProtoResult = SenseiProtos.SenseiProtoResult.parseFrom(bytes); } catch (InvalidProtocolBufferException e) { throw new IllegalArgumentException("Could not parse proto result"); } SenseiResult senseiResult = new SenseiResult(); if (senseiProtoResult.hasParsedQuery()) senseiResult.setParsedQuery(senseiProtoResult.getParsedQuery()); List<SenseiHit> hits = new ArrayList<SenseiHit>(senseiProtoResult.getHitCount()); for (SenseiProtos.SenseiHit senseiHit : senseiProtoResult.getHitList()) { hits.add(convert(senseiHit)); } senseiResult.setHits(hits.toArray(new SenseiHit[]{})); if (senseiProtoResult.hasTid()) senseiResult.setTid(senseiProtoResult.getTid()); if (senseiProtoResult.hasNumHits()) senseiResult.setNumHits((int) senseiProtoResult.getNumHits()); if (senseiProtoResult.hasTotalDocs()) senseiResult.setTotalDocs((int) senseiProtoResult.getTotalDocs()); if (senseiProtoResult.getGroupAccessibleCount() > 0) { List<SenseiProtos.FacetAccessible> groupAccessibleList = senseiProtoResult.getGroupAccessibleList(); FacetAccessible[] facetAccessibles = new FacetAccessible[groupAccessibleList.size()]; int i = 0; for (SenseiProtos.FacetAccessible protoFacetAccessible : groupAccessibleList) { FacetAccessible facetAccessible = convertFacetAccessible(protoFacetAccessible); facetAccessibles[i++] = facetAccessible; } senseiResult.setGroupAccessibles(facetAccessibles); } if (senseiProtoResult.hasFacetMap()) { senseiResult.addAll(convertFacetMap(senseiProtoResult.getFacetMap())); } if (senseiProtoResult.hasTime()) senseiResult.setTime(senseiProtoResult.getTime()); if (senseiProtoResult.hasMapReduceResult()) senseiResult.setMapReduceResult(convertMapReduceResult(senseiProtoResult.getMapReduceResult())); if (senseiProtoResult.getErrorCount() > 0) { List<SenseiProtos.SenseiError> errorList = senseiProtoResult.getErrorList(); for(SenseiProtos.SenseiError error : errorList) { senseiResult.addError(convert(error)); } } return senseiResult; } private SenseiProtos.BooleanOperator convertOperator(BrowseSelection.ValueOperation valueOperation) { switch (valueOperation) { case ValueOperationAnd: return SenseiProtos.BooleanOperator.AND; case ValueOperationOr: return SenseiProtos.BooleanOperator.OR; default: throw new IllegalArgumentException(); } } private BrowseSelection.ValueOperation convertOperator(SenseiProtos.BooleanOperator valueOperation) { switch (valueOperation) { case AND: return BrowseSelection.ValueOperation.ValueOperationAnd; case OR: return BrowseSelection.ValueOperation.ValueOperationOr; default: throw new IllegalArgumentException(); } } private SenseiProtos.StringProperties convertProperties(Map<?, ?> map) { SenseiProtos.StringProperties.Builder stringPropertiesBuilder = SenseiProtos.StringProperties.newBuilder(); for (Map.Entry<?, ?> entry : map.entrySet()) { String key = entry.getKey().toString(); String value = entry.getValue().toString(); stringPropertiesBuilder.addKey(key); stringPropertiesBuilder.addValue(value); } return stringPropertiesBuilder.build(); } private Map<String, String> convertProperties(SenseiProtos.StringProperties stringProperties) { Map<String, String> results = new HashMap<String, String>(); for (int i = 0; i < stringProperties.getKeyCount(); i++) { results.put(stringProperties.getKey(i), stringProperties.getValue(i)); } return results; } private SenseiProtos.BrowseSelection convertBrowseSelection(BrowseSelection browseSelection) { BrowseSelection.ValueOperation selectionOperation = browseSelection.getSelectionOperation(); return SenseiProtos.BrowseSelection.newBuilder().setOperator(convertOperator(selectionOperation)).setFieldName( browseSelection.getFieldName()).addAllValue(browseSelection.getValues() == null ? Collections.<String>emptyList() : Arrays.asList( browseSelection.getValues())).addAllNotValue(browseSelection.getNotValues() == null ? Collections.<String>emptyList() : Arrays.asList( browseSelection.getNotValues())).setProperties(convertProperties(browseSelection.getSelectionProperties())).build(); } private BrowseSelection convertBrowseSelection(SenseiProtos.BrowseSelection protoBrowseSelection) { BrowseSelection browseSelection = new BrowseSelection(protoBrowseSelection.getFieldName()); browseSelection.setSelectionOperation(convertOperator(protoBrowseSelection.getOperator())); browseSelection.setValues(protoBrowseSelection.getValueList().toArray(new String[]{})); browseSelection.setNotValues(protoBrowseSelection.getNotValueList().toArray(new String[]{})); browseSelection.setSelectionProperties(convertProperties(protoBrowseSelection.getProperties())); return browseSelection; } private SenseiProtos.Locale convertLocale(Locale locale) { String country = locale.getCountry(); String language = locale.getLanguage(); String variant = locale.getVariant(); SenseiProtos.Locale.Builder builder = SenseiProtos.Locale.newBuilder(); if (country != null) builder.setCountry(country); if (language != null) builder.setLanguage(language); if (variant != null) builder.setVariant(variant); return builder.build(); } private Locale convertLocale(SenseiProtos.Locale locale) { String country = locale.hasCountry() ? locale.getCountry() : ""; String language = locale.hasLanguage() ? locale.getLanguage() : ""; String variant = locale.hasVariant() ? locale.getVariant() : ""; return new Locale(language, country, variant); } private SenseiProtos.SortField convertSortField(SortField sortField) { SenseiProtos.SortField.Builder builder = SenseiProtos.SortField.newBuilder(); if (sortField.getField() != null) builder.setField(sortField.getField()); builder.setType(sortField.getType()); if (sortField.getLocale() != null) builder.setLocale(convertLocale(sortField.getLocale())); builder.setReverse(sortField.getReverse()); return builder.build(); } private SortField convertSortField(SenseiProtos.SortField protoSortField) { String field = protoSortField.hasField() ? protoSortField.getField() : null; SortField sortField = new SortField(field, protoSortField.getType(), protoSortField.getReverse()); return sortField; } private SenseiProtos.SortOrder convertSortOrder(FacetSpec.FacetSortSpec facetSortSpec) { switch (facetSortSpec) { case OrderValueAsc: return SenseiProtos.SortOrder.ASCENDING; case OrderHitsDesc: return SenseiProtos.SortOrder.DESCENDING; case OrderByCustom: return SenseiProtos.SortOrder.CUSTOM; default: throw new IllegalArgumentException(); } } private FacetSpec.FacetSortSpec convertSortOrder(SenseiProtos.SortOrder sortOrder) { switch (sortOrder) { case ASCENDING: return FacetSpec.FacetSortSpec.OrderValueAsc; case DESCENDING: return FacetSpec.FacetSortSpec.OrderHitsDesc; case CUSTOM: return FacetSpec.FacetSortSpec.OrderByCustom; default: throw new IllegalArgumentException(); } } private SenseiProtos.FacetSpec convertFacetSpec(String field, FacetSpec facetSpec) { return SenseiProtos.FacetSpec.newBuilder().setOrderBy(convertSortOrder(facetSpec.getOrderBy())).setMax(facetSpec.getMaxCount()).setExpandSelection( facetSpec.isExpandSelection()).setMinCount(facetSpec.getMinHitCount()).setProperties(convertProperties(facetSpec.getProperties())).setField( field).build(); } private Map<String, FacetSpec> convertFacetSpecs(Iterable<SenseiProtos.FacetSpec> facetSpecs) { Map<String, FacetSpec> result = new HashMap<String, FacetSpec>(); for (SenseiProtos.FacetSpec protoFacetSpec : facetSpecs) { FacetSpec facetSpec = new FacetSpec(); facetSpec.setOrderBy(convertSortOrder(protoFacetSpec.getOrderBy())); facetSpec.setMaxCount(protoFacetSpec.getMax()); facetSpec.setExpandSelection(protoFacetSpec.getExpandSelection()); facetSpec.setMinHitCount(protoFacetSpec.getMinCount()); facetSpec.setProperties(convertProperties(protoFacetSpec.getProperties())); result.put(protoFacetSpec.getField(), facetSpec); } return result; } private SenseiProtos.SenseiMapReduceFunction convertMapReduce(SenseiMapReduce mapReduce) { if (mapReduce instanceof AvgMapReduce) { return SenseiProtos.SenseiMapReduceFunction.AVG; } else if (mapReduce instanceof CountGroupByMapReduce) { return SenseiProtos.SenseiMapReduceFunction.COUNT_GROUP_BY; } else if (mapReduce instanceof DistinctCountMapReduce) { return SenseiProtos.SenseiMapReduceFunction.DISTINCT_COUNT; } else if (mapReduce instanceof DistinctUIDCount) { return SenseiProtos.SenseiMapReduceFunction.DISTINCT_UID; } else if (mapReduce instanceof FacetCountsMapReduce) { return SenseiProtos.SenseiMapReduceFunction.FACET_COUNTS; } else if (mapReduce instanceof HashSetDistinctCountMapReduce) { return SenseiProtos.SenseiMapReduceFunction.HASH_SET_DISTINCT_COUNT; } else if (mapReduce instanceof MaxMapReduce) { return SenseiProtos.SenseiMapReduceFunction.MAX; } else if (mapReduce instanceof MinMapReduce) { return SenseiProtos.SenseiMapReduceFunction.MIN; } else if (mapReduce instanceof SumMapReduce) { return SenseiProtos.SenseiMapReduceFunction.SUM; } else { return SenseiProtos.SenseiMapReduceFunction.UNKNOWN; } } private SenseiMapReduce convertMapReduce(SenseiProtos.SenseiMapReduceFunction mapReduce) { switch (mapReduce) { case AVG: return new AvgMapReduce(); case COUNT_GROUP_BY: return new CountGroupByMapReduce(); case DISTINCT_COUNT: return new DistinctCountMapReduce(); case DISTINCT_UID: return new DistinctUIDCount(); case FACET_COUNTS: return new FacetCountsMapReduce(); case HASH_SET_DISTINCT_COUNT: return new HashSetDistinctCountMapReduce(); case MAX: return new MaxMapReduce(); case MIN: return new MinMapReduce(); case SUM: return new SumMapReduce(); case UNKNOWN: return null; default: throw new IllegalArgumentException("Cannot translate " + mapReduce + " from protobuf"); } } private SenseiProtos.FacetHandlerInitializerParams convertFacetParams(Map<String, FacetHandlerInitializerParam> facetHandlerInitializerParamMap) { SenseiProtos.FacetHandlerInitializerParams.Builder builder = SenseiProtos.FacetHandlerInitializerParams.newBuilder(); for (Map.Entry<String, FacetHandlerInitializerParam> entry : facetHandlerInitializerParamMap.entrySet()) { builder.addKey(entry.getKey()); builder.addValue(convertFacetParam(entry.getValue())); } return builder.build(); } private Map<String, FacetHandlerInitializerParam> convertFacetParams(SenseiProtos.FacetHandlerInitializerParams protoFacetHandlerInitializerParams) { Map<String, FacetHandlerInitializerParam> result = new HashMap<String, FacetHandlerInitializerParam>(); for (int i = 0; i < protoFacetHandlerInitializerParams.getKeyCount(); i++) { result.put(protoFacetHandlerInitializerParams.getKey(i), convertFacetParam(protoFacetHandlerInitializerParams.getValue(i))); } return result; } private SenseiProtos.FacetHandlerInitializerParam convertFacetParam(FacetHandlerInitializerParam facetHandlerInitializerParam) { SenseiProtos.FacetHandlerInitializerParam.Builder protoParams = SenseiProtos.FacetHandlerInitializerParam.newBuilder(); for (String paramName : facetHandlerInitializerParam.getBooleanParamNames()) { SenseiProtos.BooleanParams.Builder paramBuilder = SenseiProtos.BooleanParams.newBuilder(); paramBuilder.setKey(paramName); boolean[] param = facetHandlerInitializerParam.getBooleanParam(paramName); if(param != null) { for (int i = 0; i < param.length; i++) { paramBuilder.addValue(param[i]); } } else { paramBuilder.setIsNull(true); } protoParams.addBooleanParam(paramBuilder.build()); } for (String paramName : facetHandlerInitializerParam.getIntParamNames()) { SenseiProtos.IntParams.Builder paramBuilder = SenseiProtos.IntParams.newBuilder(); paramBuilder.setKey(paramName); int[] param = facetHandlerInitializerParam.getIntParam(paramName); if (param != null) { for (int i = 0; i < param.length; i++) { paramBuilder.addValue(param[i]); } } else { paramBuilder.setIsNull(true); } protoParams.addIntParam(paramBuilder.build()); } for (String paramName : facetHandlerInitializerParam.getLongParamNames()) { SenseiProtos.LongParams.Builder paramBuilder = SenseiProtos.LongParams.newBuilder(); paramBuilder.setKey(paramName); long[] param = facetHandlerInitializerParam.getLongParam(paramName); if (param != null) { for (int i = 0; i < param.length; i++) { paramBuilder.addValue(param[i]); } } else { paramBuilder.setIsNull(true); } protoParams.addLongParam(paramBuilder.build()); } for (String paramName : facetHandlerInitializerParam.getDoubleParamNames()) { SenseiProtos.DoubleParams.Builder paramBuilder = SenseiProtos.DoubleParams.newBuilder(); paramBuilder.setKey(paramName); double[] param = facetHandlerInitializerParam.getDoubleParam(paramName); if (param != null) { for (int i = 0; i < param.length; i++) { paramBuilder.addValue(param[i]); } } else { paramBuilder.setIsNull(true); } protoParams.addDoubleParam(paramBuilder.build()); } for (String paramName : facetHandlerInitializerParam.getStringParamNames()) { SenseiProtos.StringParams.Builder paramBuilder = SenseiProtos.StringParams.newBuilder(); paramBuilder.setKey(paramName); List<String> param = facetHandlerInitializerParam.getStringParam(paramName); if (param != null) { paramBuilder.addAllValue(param); } else { paramBuilder.setIsNull(true); } protoParams.addStringParam(paramBuilder.build()); } for (String paramName : facetHandlerInitializerParam.getByteArrayParamNames()) { SenseiProtos.ByteArrayParams.Builder paramBuilder = SenseiProtos.ByteArrayParams.newBuilder(); paramBuilder.setKey(paramName); byte[] param = facetHandlerInitializerParam.getByteArrayParam(paramName); if (param != null) { for (int i = 0; i < param.length; i++) { paramBuilder.setValue(ByteString.copyFrom(param)); } } else { paramBuilder.setIsNull(true); } protoParams.addByteParam(paramBuilder.build()); } return protoParams.build(); } private FacetHandlerInitializerParam convertFacetParam(SenseiProtos.FacetHandlerInitializerParam protoFacetHandlerInitializerParam) { DefaultFacetHandlerInitializerParam facetHandlerInitializerParam = new DefaultFacetHandlerInitializerParam(); for (SenseiProtos.BooleanParams param : protoFacetHandlerInitializerParam.getBooleanParamList()) { boolean[] value = null; if(!param.getIsNull()) { value = new boolean[param.getValueCount()]; for (int i = 0; i < value.length; i++) { value[i] = param.getValue(i); } } facetHandlerInitializerParam.putBooleanParam(param.getKey(), value); } for (SenseiProtos.IntParams param : protoFacetHandlerInitializerParam.getIntParamList()) { int[] value = null; if (!param.getIsNull()) { value = new int[param.getValueCount()]; for (int i = 0; i < value.length; i++) { value[i] = param.getValue(i); } } facetHandlerInitializerParam.putIntParam(param.getKey(), value); } for (SenseiProtos.LongParams param : protoFacetHandlerInitializerParam.getLongParamList()) { long[] value = null; if (!param.getIsNull()) { value = new long[param.getValueCount()]; for (int i = 0; i < value.length; i++) { value[i] = param.getValue(i); } } facetHandlerInitializerParam.putLongParam(param.getKey(), value); } for (SenseiProtos.StringParams param : protoFacetHandlerInitializerParam.getStringParamList()) { List<String> value = null; if(!param.getIsNull()) { value = param.getValueList(); } facetHandlerInitializerParam.putStringParam(param.getKey(), value); } for (SenseiProtos.DoubleParams param : protoFacetHandlerInitializerParam.getDoubleParamList()) { double[] value = null; if (!param.getIsNull()) { value = new double[param.getValueCount()]; for (int i = 0; i < value.length; i++) { value[i] = param.getValue(i); } } facetHandlerInitializerParam.putDoubleParam(param.getKey(), value); } for (SenseiProtos.StringParams param : protoFacetHandlerInitializerParam.getStringParamList()) { List<String> value = null; if (!param.getIsNull()) { value = param.getValueList(); } facetHandlerInitializerParam.putStringParam(param.getKey(), value); } for (SenseiProtos.ByteArrayParams param : protoFacetHandlerInitializerParam.getByteParamList()) { ByteString value = null; if (!param.getIsNull()) { value = param.getValue(); } facetHandlerInitializerParam.putByteArrayParam(param.getKey(), value.toByteArray()); } return facetHandlerInitializerParam; } }