blob: f5f8ec9303f1113f3dfd7cfa2eae6cfa0ac706f7 [file] [log] [blame]
/*
* 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.geode.cache.lucene.internal.repository.serializer;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FloatPoint;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.util.BytesRef;
import org.apache.geode.DataSerializer;
import org.apache.geode.InternalGemFireError;
import org.apache.geode.internal.util.BlobHelper;
/**
* Static utility functions for mapping objects to lucene documents
*/
public class SerializerUtil {
private static final String KEY_FIELD = "_KEY";
private static final Set<Class> SUPPORTED_PRIMITIVE_TYPES;
static {
HashSet<Class> primitiveTypes = new HashSet<>();
primitiveTypes.add(String.class);
primitiveTypes.add(long.class);
primitiveTypes.add(int.class);
primitiveTypes.add(float.class);
primitiveTypes.add(double.class);
primitiveTypes.add(Long.class);
primitiveTypes.add(Integer.class);
primitiveTypes.add(Float.class);
primitiveTypes.add(Double.class);
SUPPORTED_PRIMITIVE_TYPES = Collections.unmodifiableSet(primitiveTypes);
}
/**
* A small buffer for converting keys to byte[] arrays.
*/
private static ThreadLocal<ByteArrayOutputStream> LOCAL_BUFFER =
new ThreadLocal<ByteArrayOutputStream>() {
@Override
protected ByteArrayOutputStream initialValue() {
return new ByteArrayOutputStream();
}
};
private SerializerUtil() {}
/**
* Add a Apache Geode key to a document
*/
public static void addKey(Object key, Document doc) {
if (key instanceof String) {
doc.add(new StringField(KEY_FIELD, (String) key, Store.YES));
} else {
doc.add(new StringField(KEY_FIELD, keyToBytes(key), Store.YES));
}
}
/**
* Add a field to the document.
*
* @return true if the field was successfully added
*/
public static boolean addField(Document doc, String field, Object fieldValue) {
Class<?> clazz = fieldValue.getClass();
if (clazz == String.class) {
doc.add(new TextField(field, (String) fieldValue, Store.NO));
} else if (clazz == Long.class) {
doc.add(new LongPoint(field, (Long) fieldValue));
} else if (clazz == Integer.class) {
doc.add(new IntPoint(field, (Integer) fieldValue));
} else if (clazz == Float.class) {
doc.add(new FloatPoint(field, (Float) fieldValue));
} else if (clazz == Double.class) {
doc.add(new DoublePoint(field, (Double) fieldValue));
} else {
return false;
}
return true;
}
/**
* Return true if a field type can be written to a lucene document.
*/
public static boolean isSupported(Class<?> type) {
return SUPPORTED_PRIMITIVE_TYPES.contains(type);
}
public static Collection<Class> supportedPrimitiveTypes() {
return SUPPORTED_PRIMITIVE_TYPES;
}
/**
* Extract the Apache Geode key from a lucene document
*/
public static Object getKey(Document doc) {
IndexableField field = doc.getField(KEY_FIELD);
if (field.stringValue() != null) {
return field.stringValue();
} else {
return keyFromBytes(field.binaryValue());
}
}
/**
* Extract the Apache Geode key term from a lucene document
*/
public static Term getKeyTerm(Document doc) {
IndexableField field = doc.getField(KEY_FIELD);
if (field.stringValue() != null) {
return new Term(KEY_FIELD, field.stringValue());
} else {
return new Term(KEY_FIELD, field.binaryValue());
}
}
/**
* Convert a Apache Geode key into a key search term that can be used to update or delete the
* document associated with this key.
*/
public static Term toKeyTerm(Object key) {
if (key instanceof String) {
return new Term(KEY_FIELD, (String) key);
} else {
return new Term(KEY_FIELD, keyToBytes(key));
}
}
private static Object keyFromBytes(BytesRef bytes) {
try {
return BlobHelper.deserializeBlob(bytes.bytes);
} catch (ClassNotFoundException | IOException e) {
throw new InternalGemFireError(e);
}
}
/**
* Convert a key to a byte array.
*/
private static BytesRef keyToBytes(Object key) {
ByteArrayOutputStream buffer = LOCAL_BUFFER.get();
try {
DataOutputStream out = new DataOutputStream(buffer);
DataSerializer.writeObject(key, out);
out.flush();
BytesRef result = new BytesRef(buffer.toByteArray());
buffer.reset();
return result;
} catch (IOException e) {
throw new InternalGemFireError("Unable to serialize key", e);
}
}
}