| /** |
| * 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.apex.malhar.lib.appdata.gpo; |
| |
| import java.io.Serializable; |
| import java.lang.reflect.Array; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.codehaus.jettison.json.JSONArray; |
| import org.codehaus.jettison.json.JSONException; |
| import org.codehaus.jettison.json.JSONObject; |
| |
| import org.apache.apex.malhar.lib.appdata.schemas.Fields; |
| import org.apache.apex.malhar.lib.appdata.schemas.FieldsDescriptor; |
| import org.apache.apex.malhar.lib.appdata.schemas.ResultFormatter; |
| import org.apache.apex.malhar.lib.appdata.schemas.Type; |
| import org.apache.apex.malhar.lib.util.PojoUtils; |
| import org.apache.apex.malhar.lib.util.PojoUtils.Getter; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterBoolean; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterByte; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterChar; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterDouble; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterFloat; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterInt; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterLong; |
| import org.apache.apex.malhar.lib.util.PojoUtils.GetterShort; |
| import org.apache.commons.lang3.mutable.MutableInt; |
| |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.Maps; |
| import com.google.common.collect.Sets; |
| |
| /** |
| * This class holds utility methods for serializing and deserializing {@link GPOMutable} objects to/from bytes and JSON. |
| * There are also utility methods for converting POJOs into GPOMutable objects. |
| * @since 3.0.0 |
| */ |
| public class GPOUtils |
| { |
| /** |
| * This class should not be instantiated |
| */ |
| private GPOUtils() |
| { |
| //Do nothing |
| } |
| |
| /** |
| * This utility method converts a field to type map specified in JSON into |
| * a java map from field to type. An example of a JSON field to type map |
| * is the following: |
| * <br/> |
| * <br/> |
| * <pre> |
| * {@code |
| * { |
| * "fieldName1":"integer", |
| * "fieldName2":"string", |
| * "fieldName3":"byte", |
| * ... |
| * } |
| * } |
| * </pre> |
| * @param jo The {@link JSONObject} containing the JSON to convert. |
| * @return A java Map from field name to the corresponding field type. |
| * @throws JSONException |
| */ |
| @SuppressWarnings("unchecked") |
| public static Map<String, Type> buildTypeMap(JSONObject jo) throws JSONException |
| { |
| Map<String, Type> fieldToType = Maps.newHashMap(); |
| for (Iterator<String> keys = (Iterator<String>)jo.keys(); |
| keys.hasNext();) { |
| String key = keys.next(); |
| String val = jo.getString(key); |
| Type type = Type.getTypeEx(val); |
| fieldToType.put(key, type); |
| } |
| |
| return fieldToType; |
| } |
| |
| /** |
| * Converts the provided JSON into a GPOMutable object with the provided {@link FieldsDescriptor} |
| * @param fieldsDescriptor The {@link FieldsDescriptor} to initialize the {@link GPOMutable} object with. |
| * @param dpou The JSONObject to deserialize from. |
| * @return The deserialized GPOMutable object. |
| */ |
| public static GPOMutable deserialize(FieldsDescriptor fieldsDescriptor, JSONObject dpou) |
| { |
| GPOMutable gpo = new GPOMutable(fieldsDescriptor); |
| @SuppressWarnings("unchecked") |
| Iterator<String> itr = (Iterator<String>)dpou.keys(); |
| |
| while (itr.hasNext()) { |
| String field = itr.next(); |
| setFieldFromJSON(gpo, field, dpou); |
| } |
| |
| return gpo; |
| } |
| |
| /** |
| * This method deserializes the fields in the given {@link FieldsDescriptor} into a map. |
| * @param fieldsDescriptor The {@link FieldsDescriptor} to fetch fields from. |
| * @param dpou The {@link JSONObject} which contains the fields whose values need to be fetched. |
| * @return A {@link Map} whose keys are field names, and whose values are possible values for those fields. |
| */ |
| public static Map<String, Set<Object>> deserializeToMap(FieldsDescriptor fieldsDescriptor, JSONObject dpou) |
| { |
| Map<String, Set<Object>> keyToValues = Maps.newHashMap(); |
| |
| for (String key : fieldsDescriptor.getFields().getFields()) { |
| if (!dpou.has(key)) { |
| throw new IllegalArgumentException("The given key " + key + " is not contained in the given JSON"); |
| } |
| |
| Set<Object> keyValues; |
| Object keyValue; |
| |
| try { |
| keyValue = dpou.get(key); |
| } catch (JSONException ex) { |
| throw new IllegalStateException("This should never happen", ex); |
| } |
| |
| if (keyValue instanceof JSONArray) { |
| |
| JSONArray ja = (JSONArray)keyValue; |
| keyValues = Sets.newHashSetWithExpectedSize(ja.length()); |
| |
| Type type = fieldsDescriptor.getType(key); |
| |
| for (int index = 0; index < ja.length(); index++) { |
| keyValues.add(getFieldFromJSON(type, ja, index)); |
| } |
| |
| } else if (keyValue instanceof JSONObject) { |
| throw new UnsupportedOperationException("Cannot extract objects from JSONObjects"); |
| } else { |
| keyValues = Sets.newHashSetWithExpectedSize(1); |
| keyValues.add(getFieldFromJSON(fieldsDescriptor, key, dpou)); |
| } |
| |
| keyToValues.put(key, keyValues); |
| } |
| |
| return keyToValues; |
| } |
| |
| /** |
| * This is a helper method for deserialization of a GPOMutable from JSON. It allows you to select a field from |
| * a JSONObject in a json array and set it on the provided GPOMutable object. The format of the JSONArray should |
| * be the following: |
| * <br/> |
| * <br/> |
| * <pre> |
| * {@code |
| * [ |
| * { |
| * "fieldName1":"val1", |
| * "fieldName2":"val2", |
| * ... |
| * }, |
| * { |
| * "fieldName1":"valx", |
| * ... |
| * } |
| * ... |
| * ] |
| * } |
| * </pre> |
| * <br/> |
| * <br/> |
| * @param gpo The {@link GPOMutable} to set fields on. |
| * @param type The type of the field that will be set. |
| * @param field The name of the field that will be set. |
| * The name of the field must be the same in both the {@link GPOMutable}'s {@link FieldsDescriptor} object and in the JSONObject. |
| * @param jo The JSONOArray holding JSONObjects to deserialize from. |
| * @param index The index of the JSONArray |
| */ |
| public static void setFieldFromJSON(GPOMutable gpo, Type type, String field, JSONArray jo, int index) |
| { |
| GPOType gpoType = GPOType.GPO_TYPE_ARRAY[type.ordinal()]; |
| gpoType.setFieldFromJSON(gpo, field, jo, index); |
| } |
| |
| /** |
| * This is a utility method to deserialize data from the given JSONObject into a {@link GPOMutable} object. |
| * The format of the JSON to deserialize from should look like this. |
| * <pre> |
| * {@code |
| * { |
| * "fieldName1":"val1", |
| * "fieldName2":"val2", |
| * ... |
| * } |
| * } |
| * </pre> |
| * @param gpo The {@link GPOMutable} object to deserialize into. |
| * @param field The name of the field to take from the JSON and place into the {@link GPOMutable} object. |
| * The name of the field must be the same in the {@link FieldsDescriptor} and the {@link GPOMutable} object. |
| * @param jo The JSONObject to deserialize from. |
| */ |
| public static void setFieldFromJSON(GPOMutable gpo, String field, JSONObject jo) |
| { |
| Object val = getFieldFromJSON(gpo.getFieldDescriptor(), field, jo); |
| gpo.setFieldGeneric(field, val); |
| } |
| |
| /** |
| * This method gets the given field from the given {@link JSONObject} and converts the field to an object |
| * of the type specified in the given {@link FieldsDescriptor}. |
| * @param fd The {@link FieldsDescriptor} describing the type of each field. |
| * @param field The field to retrieve from the given {@link JSONObject}. |
| * @param jo The {@link JSONObject} to retrieve a field from. |
| * @return The value of the given field converted to an object of the correct type. |
| */ |
| public static Object getFieldFromJSON(FieldsDescriptor fd, String field, JSONObject jo) |
| { |
| Type type = fd.getType(field); |
| int intVal = 0; |
| |
| if (numericTypeIntOrSmaller(type)) { |
| try { |
| intVal = jo.getInt(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " + field + " does not have a valid " + type + " value.", ex); |
| } |
| |
| if (type != Type.INTEGER && !insideRange(type, intVal)) { |
| throw new IllegalArgumentException("The key " + field + " has a value " + intVal |
| + " which is out of range for a " + type + "."); |
| } |
| } |
| |
| if (type == Type.BOOLEAN) { |
| try { |
| return jo.getBoolean(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " + field + " does not have a valid bool value.", ex); |
| } |
| } else if (type == Type.BYTE) { |
| return ((byte)intVal); |
| } else if (type == Type.SHORT) { |
| return ((short)intVal); |
| } else if (type == Type.INTEGER) { |
| return intVal; |
| } else if (type == Type.LONG) { |
| try { |
| return jo.getLong(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " |
| + field |
| + " does not have a valid long value.", |
| ex); |
| } |
| } else if (type == Type.CHAR) { |
| String val; |
| |
| try { |
| val = jo.getString(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " |
| + field |
| + " does not have a valid character value.", |
| ex); |
| } |
| |
| if (val.length() != 1) { |
| throw new IllegalArgumentException("The key " |
| + field |
| + " has a value " |
| + val |
| + " that is not one character long."); |
| } |
| |
| return val.charAt(0); |
| } else if (type == Type.STRING) { |
| try { |
| return jo.getString(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " |
| + field |
| + " does not have a valid string value.", |
| ex); |
| } |
| } else if (type == Type.DOUBLE) { |
| try { |
| return jo.getDouble(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " |
| + field |
| + " does not have a valid double value.", |
| ex); |
| } |
| } else if (type == Type.FLOAT) { |
| try { |
| return (float)jo.getDouble(field); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The key " |
| + field |
| + " does not have a valid double value.", |
| ex); |
| } |
| } else { |
| throw new UnsupportedOperationException("The type " + type + " is not supported."); |
| } |
| } |
| |
| /** |
| * This method gets an object of the given {@link Type} from the given {@link JSONArray} at the |
| * given index. |
| * @param type The {@link Type} of the object to retrieve from the {@link JSONArray}. |
| * @param ja The {@link JSONArray} to retrieve objects from. |
| * @param index The index of the object in the {@link JSONArray} to retrieve. |
| * @return The object retrieved from the {@link JSONArray}. |
| */ |
| public static Object getFieldFromJSON(Type type, JSONArray ja, int index) |
| { |
| int intVal = 0; |
| |
| if (numericTypeIntOrSmaller(type)) { |
| try { |
| intVal = ja.getInt(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " + index + " does not have a valid " + type + " value.", ex); |
| } |
| |
| if (type != Type.INTEGER && !insideRange(type, intVal)) { |
| throw new IllegalArgumentException("The index " + index + " has a value " + intVal |
| + " which is out of range for a " + type + "."); |
| } |
| } |
| |
| if (type == Type.BOOLEAN) { |
| try { |
| return ja.getBoolean(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " + index + " does not have a valid bool value.", ex); |
| } |
| } else if (type == Type.BYTE) { |
| return ((byte)intVal); |
| } else if (type == Type.SHORT) { |
| return ((short)intVal); |
| } else if (type == Type.INTEGER) { |
| return intVal; |
| } else if (type == Type.LONG) { |
| try { |
| return ja.getLong(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " |
| + index |
| + " does not have a valid long value.", |
| ex); |
| } |
| } else if (type == Type.CHAR) { |
| String val; |
| |
| try { |
| val = ja.getString(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " |
| + index |
| + " does not have a valid character value.", |
| ex); |
| } |
| |
| if (val.length() != 1) { |
| throw new IllegalArgumentException("The index " |
| + index |
| + " has a value " |
| + val |
| + " that is not one character long."); |
| } |
| |
| return val.charAt(0); |
| } else if (type == Type.STRING) { |
| try { |
| return ja.getString(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " |
| + index |
| + " does not have a valid string value.", |
| ex); |
| } |
| } else if (type == Type.DOUBLE) { |
| try { |
| return ja.getDouble(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " |
| + index |
| + " does not have a valid double value.", |
| ex); |
| } |
| } else if (type == Type.FLOAT) { |
| try { |
| return (float)ja.getDouble(index); |
| } catch (JSONException ex) { |
| throw new IllegalArgumentException("The index " |
| + index |
| + " does not have a valid double value.", |
| ex); |
| } |
| } else { |
| throw new UnsupportedOperationException("The type " + type + " is not supported."); |
| } |
| } |
| |
| /** |
| * This utility method serializes the given fields from the given {@link GPOMutable} object into JSON using the |
| * given resultFormatter. |
| * @param gpo The {@link GPOMutable} to serialize. |
| * @param fields The fields from the given {@link GPOMutable} object to serialize. |
| * @param resultFormatter The result formatter to use when formatting the output data during serialization. |
| * @return The serialized {@link GPOMutable} object. |
| * @throws JSONException |
| */ |
| public static JSONObject serializeJSONObject(GPOMutable gpo, Fields fields, ResultFormatter resultFormatter) throws JSONException |
| { |
| JSONObject jo = new JSONObject(); |
| FieldsDescriptor fd = gpo.getFieldDescriptor(); |
| |
| for (String field : fields.getFields()) { |
| Type fieldType = fd.getType(field); |
| GPOType gpoType = GPOType.GPO_TYPE_ARRAY[fieldType.ordinal()]; |
| gpoType.serializeJSONObject(jo, gpo, field, resultFormatter); |
| } |
| |
| return jo; |
| } |
| |
| /** |
| * Serializes the given {@link GPOMutable} object with the given resultFormatter. |
| * @param gpo The {@link GPOMutable} to serialize. |
| * @param resultFormatter The result formatter to use when serializing data. |
| * @return The serialized {@link GPOMutable} object. |
| * @throws JSONException |
| */ |
| public static JSONObject serializeJSONObject(GPOMutable gpo, ResultFormatter resultFormatter) throws JSONException |
| { |
| return serializeJSONObject(gpo, gpo.getFieldDescriptor().getFields(), resultFormatter); |
| } |
| |
| /** |
| * Computes the number of bytes required to serialize the given {@link GPOMutable} object. Excluding the |
| * object fields in the {@link GPOMutable}. |
| * @param gpo The {@link GPOMutable} object to compute a serialized size for. |
| * @return The serialized size for the given {@link GPOMutable} object. |
| */ |
| public static int serializedLength(GPOMutable gpo) |
| { |
| int arrayLength = 0; |
| FieldsDescriptor fd = gpo.getFieldDescriptor(); |
| |
| List<Type> types = fd.getTypesList(); |
| |
| for (int typeIndex = 0; typeIndex < types.size(); typeIndex++) { |
| Type type = types.get(typeIndex); |
| |
| switch (type) { |
| case STRING: { |
| for (String val : gpo.getFieldsString()) { |
| arrayLength += Type.INTEGER.getByteSize(); |
| arrayLength += val.getBytes().length; |
| } |
| break; |
| } |
| case OBJECT: { |
| //Don't include objects. |
| break; |
| } |
| default: { |
| arrayLength += fd.getTypeToFields().get(type).size() * |
| type.getByteSize(); |
| } |
| } |
| } |
| |
| return arrayLength; |
| } |
| |
| /** |
| * Serializes the given {@link GPOMutable} object to an array of bytes. |
| * @param gpo The {@link GPOMutable} object to serialize. |
| * @param byteArrayList A byte array list to pack serialized data into. Note that |
| * it is assumed that the byteArrayList is empty when passed to this method. |
| * @return The serialized {@link GPOMutable} object. |
| */ |
| public static byte[] serialize(GPOMutable gpo, GPOByteArrayList byteArrayList) |
| { |
| int slength = serializedLength(gpo); |
| byte[] sbytes = new byte[slength]; |
| MutableInt offset = new MutableInt(0); |
| |
| boolean[] fieldsBoolean = gpo.getFieldsBoolean(); |
| if (fieldsBoolean != null) { |
| for (int index = 0; index < fieldsBoolean.length; index++) { |
| serializeBoolean(fieldsBoolean[index], sbytes, offset); |
| } |
| } |
| |
| char[] fieldsCharacter = gpo.getFieldsCharacter(); |
| if (fieldsCharacter != null) { |
| for (int index = 0; index < fieldsCharacter.length; index++) { |
| serializeChar(fieldsCharacter[index], sbytes, offset); |
| } |
| } |
| |
| byte[] fieldsByte = gpo.getFieldsByte(); |
| if (fieldsByte != null) { |
| for (int index = 0; index < fieldsByte.length; index++) { |
| serializeByte(fieldsByte[index], sbytes, offset); |
| } |
| } |
| |
| short[] fieldsShort = gpo.getFieldsShort(); |
| if (fieldsShort != null) { |
| for (int index = 0; index < fieldsShort.length; index++) { |
| serializeShort(fieldsShort[index], sbytes, offset); |
| } |
| } |
| |
| int[] fieldsInteger = gpo.getFieldsInteger(); |
| if (fieldsInteger != null) { |
| for (int index = 0; index < fieldsInteger.length; index++) { |
| serializeInt(fieldsInteger[index], sbytes, offset); |
| } |
| } |
| |
| long[] fieldsLong = gpo.getFieldsLong(); |
| if (fieldsLong != null) { |
| for (int index = 0; index < fieldsLong.length; index++) { |
| serializeLong(fieldsLong[index], sbytes, offset); |
| } |
| } |
| |
| float[] fieldsFloat = gpo.getFieldsFloat(); |
| if (fieldsFloat != null) { |
| for (int index = 0; index < fieldsFloat.length; index++) { |
| serializeFloat(fieldsFloat[index], sbytes, offset); |
| } |
| } |
| |
| double[] fieldsDouble = gpo.getFieldsDouble(); |
| if (fieldsDouble != null) { |
| for (int index = 0; index < fieldsDouble.length; index++) { |
| serializeDouble(fieldsDouble[index], sbytes, offset); |
| } |
| } |
| |
| String[] fieldsString = gpo.getFieldsString(); |
| if (fieldsString != null) { |
| for (int index = 0; index < fieldsString.length; index++) { |
| serializeString(fieldsString[index], sbytes, offset); |
| } |
| } |
| |
| if (sbytes.length > 0) { |
| byteArrayList.add(sbytes); |
| } |
| |
| Object[] fieldsObject = gpo.getFieldsObject(); |
| Serde[] serdes = gpo.getFieldDescriptor().getSerdes(); |
| if (fieldsObject != null) { |
| for (int index = 0; index < fieldsObject.length; index++) { |
| byteArrayList.add(serdes[index].serializeObject(fieldsObject[index])); |
| } |
| } |
| |
| byte[] bytes = byteArrayList.toByteArray(); |
| byteArrayList.clear(); |
| return bytes; |
| } |
| |
| /** |
| * Serializes the given {@link GPOMutable} object while excluding the provided fields from the serialization. |
| * @param gpo The {@link GPOMutable} to serialize. |
| * @param excludedFields The fields from the {@link GPOMutable} object to exclude. |
| * @return A byte array containing the serialized {@link GPOMutable}. |
| */ |
| public static byte[] serialize(GPOMutable gpo, Fields excludedFields) |
| { |
| int slength = serializedLength(gpo); |
| byte[] sbytes = new byte[slength]; |
| MutableInt offset = new MutableInt(0); |
| |
| Set<String> fields = gpo.getFieldDescriptor().getFields().getFields(); |
| Set<String> exFieldsSet = excludedFields.getFields(); |
| |
| for (String field : fields) { |
| if (exFieldsSet.contains(field)) { |
| continue; |
| } |
| |
| Type type = gpo.getFieldDescriptor().getType(field); |
| GPOType gpoType = GPOType.GPO_TYPE_ARRAY[type.ordinal()]; |
| gpoType.serialize(gpo, field, sbytes, offset); |
| } |
| |
| return sbytes; |
| } |
| |
| /** |
| * Deserializes a {@link GPOMutable} object from the given byte array at the given offset with the given |
| * {@link FieldsDescriptor} object. |
| * @param fd The {@link FieldsDescriptor} object which describes the schema of the {@link GPOMutable} object |
| * to deserialize. |
| * @param serializedGPO A byte array containing the serialized {@link GPOMutable} object. |
| * @param offset An offset in the byte array to start deserializing from. |
| * @return The deserialized GPOMutable. |
| */ |
| public static GPOMutable deserialize(FieldsDescriptor fd, byte[] serializedGPO, MutableInt offset) |
| { |
| GPOMutable gpo = new GPOMutable(fd); |
| |
| boolean[] fieldsBoolean = gpo.getFieldsBoolean(); |
| if (fieldsBoolean != null) { |
| for (int index = 0; index < fieldsBoolean.length; index++) { |
| fieldsBoolean[index] = deserializeBoolean(serializedGPO, offset); |
| } |
| } |
| |
| char[] fieldsCharacter = gpo.getFieldsCharacter(); |
| if (fieldsCharacter != null) { |
| for (int index = 0; index < fieldsCharacter.length; index++) { |
| fieldsCharacter[index] = deserializeChar(serializedGPO, offset); |
| } |
| } |
| |
| byte[] fieldsByte = gpo.getFieldsByte(); |
| if (fieldsByte != null) { |
| for (int index = 0; index < fieldsByte.length; index++) { |
| fieldsByte[index] = deserializeByte(serializedGPO, offset); |
| } |
| } |
| |
| short[] fieldsShort = gpo.getFieldsShort(); |
| if (fieldsShort != null) { |
| for (int index = 0; index < fieldsShort.length; index++) { |
| fieldsShort[index] = deserializeShort(serializedGPO, offset); |
| } |
| } |
| |
| int[] fieldsInteger = gpo.getFieldsInteger(); |
| if (fieldsInteger != null) { |
| for (int index = 0; index < fieldsInteger.length; index++) { |
| fieldsInteger[index] = deserializeInt(serializedGPO, offset); |
| } |
| } |
| |
| long[] fieldsLong = gpo.getFieldsLong(); |
| if (fieldsLong != null) { |
| for (int index = 0; index < fieldsLong.length; index++) { |
| fieldsLong[index] = deserializeLong(serializedGPO, offset); |
| } |
| } |
| |
| float[] fieldsFloat = gpo.getFieldsFloat(); |
| if (fieldsFloat != null) { |
| for (int index = 0; index < fieldsFloat.length; index++) { |
| fieldsFloat[index] = deserializeFloat(serializedGPO, offset); |
| } |
| } |
| |
| double[] fieldsDouble = gpo.getFieldsDouble(); |
| if (fieldsDouble != null) { |
| for (int index = 0; index < fieldsDouble.length; index++) { |
| fieldsDouble[index] = deserializeDouble(serializedGPO, offset); |
| } |
| } |
| |
| String[] fieldsString = gpo.getFieldsString(); |
| if (fieldsString != null) { |
| for (int index = 0; index < fieldsString.length; index++) { |
| fieldsString[index] = deserializeString(serializedGPO, offset); |
| } |
| } |
| |
| Object[] fieldsObject = gpo.getFieldsObject(); |
| Serde[] serdes = fd.getSerdes(); |
| if (fieldsObject != null) { |
| for (int index = 0; index < fieldsObject.length; index++) { |
| fieldsObject[index] = serdes[index].deserializeObject(serializedGPO, offset); |
| } |
| } |
| |
| return gpo; |
| } |
| |
| /** |
| * Deserializes a {@link GPOMutable} object from the given byte array at the given offset, which was |
| * serialized with the given {@link FieldsDescriptor} with the given fields excluded. |
| * @param fieldsDescriptor The {@link FieldsDescriptor} object corresponding to the {@link GPOMutable}. |
| * @param excludedFields The fields to exclude from serializing the {@link GPOMutable}. |
| * @param serializedGPO The array containing the serialized {@link GPOMutable}. |
| * @param offset The offset in the provided array to start deserializing from. |
| * @return The deserialized {@link GPOMutable}. |
| */ |
| public static GPOMutable deserialize(FieldsDescriptor fieldsDescriptor, Fields excludedFields, byte[] serializedGPO, |
| int offset) |
| { |
| GPOMutable gpo = new GPOMutable(fieldsDescriptor); |
| MutableInt offsetM = new MutableInt(offset); |
| |
| Set<String> exFieldsSet = excludedFields.getFields(); |
| |
| for (String field : fieldsDescriptor.getFields().getFields()) { |
| if (exFieldsSet.contains(field)) { |
| continue; |
| } |
| |
| Type type = fieldsDescriptor.getType(field); |
| GPOType gpoType = GPOType.GPO_TYPE_ARRAY[type.ordinal()]; |
| gpoType.deserialize(gpo, field, serializedGPO, offsetM); |
| } |
| |
| return gpo; |
| } |
| |
| /** |
| * This method deserializes a string from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized string. |
| */ |
| public static String deserializeString(byte[] buffer, MutableInt offset) |
| { |
| int length = deserializeInt(buffer, offset); |
| |
| String val = new String(buffer, offset.intValue(), length); |
| offset.add(length); |
| return val; |
| } |
| |
| /** |
| * This method serializes the given string to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeString(String val, byte[] buffer, MutableInt offset) |
| { |
| byte[] stringBytes = val.getBytes(); |
| int length = stringBytes.length; |
| |
| serializeInt(length, buffer, offset); |
| |
| for (int index = 0; index < length; index++) { |
| buffer[offset.intValue() + index] = stringBytes[index]; |
| } |
| |
| offset.add(length); |
| } |
| |
| public static byte[] serializeString(String val) |
| { |
| byte[] stringBytes = val.getBytes(); |
| byte[] length = GPOUtils.serializeInt(stringBytes.length); |
| |
| byte[] serialized = new byte[stringBytes.length + length.length]; |
| |
| System.arraycopy(length, 0, serialized, 0, length.length); |
| System.arraycopy(stringBytes, 0, serialized, length.length, stringBytes.length); |
| |
| return serialized; |
| } |
| |
| /** |
| * This method deserializes a long from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized long. |
| */ |
| public static long deserializeLong(byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| long val = ((((long)buffer[0 + offsetInt]) & 0xFFL) << 56) | |
| ((((long)buffer[1 + offsetInt]) & 0xFFL) << 48) | |
| ((((long)buffer[2 + offsetInt]) & 0xFFL) << 40) | |
| ((((long)buffer[3 + offsetInt]) & 0xFFL) << 32) | |
| ((((long)buffer[4 + offsetInt]) & 0xFFL) << 24) | |
| ((((long)buffer[5 + offsetInt]) & 0xFFL) << 16) | |
| ((((long)buffer[6 + offsetInt]) & 0xFFL) << 8) | |
| (((long)buffer[7 + offsetInt]) & 0xFFL); |
| |
| offset.add(Type.LONG.getByteSize()); |
| return val; |
| } |
| |
| /** |
| * This method serializes the given long to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeLong(long val, byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| buffer[0 + offsetInt] = (byte)((val >> 56) & 0xFFL); |
| buffer[1 + offsetInt] = (byte)((val >> 48) & 0xFFL); |
| buffer[2 + offsetInt] = (byte)((val >> 40) & 0xFFL); |
| buffer[3 + offsetInt] = (byte)((val >> 32) & 0xFFL); |
| buffer[4 + offsetInt] = (byte)((val >> 24) & 0xFFL); |
| buffer[5 + offsetInt] = (byte)((val >> 16) & 0xFFL); |
| buffer[6 + offsetInt] = (byte)((val >> 8) & 0xFFL); |
| buffer[7 + offsetInt] = (byte)(val & 0xFFL); |
| |
| offset.add(Type.LONG.getByteSize()); |
| } |
| |
| /** |
| * Serializes the given long value to an array of bytes. |
| * @param val The long value to serialize. |
| * @return The serialized long value. |
| */ |
| public static byte[] serializeLong(long val) |
| { |
| byte[] buffer = new byte[Type.LONG.getByteSize()]; |
| |
| buffer[0] = (byte)((val >> 56) & 0xFFL); |
| buffer[1] = (byte)((val >> 48) & 0xFFL); |
| buffer[2] = (byte)((val >> 40) & 0xFFL); |
| buffer[3] = (byte)((val >> 32) & 0xFFL); |
| buffer[4] = (byte)((val >> 24) & 0xFFL); |
| buffer[5] = (byte)((val >> 16) & 0xFFL); |
| buffer[6] = (byte)((val >> 8) & 0xFFL); |
| buffer[7] = (byte)(val & 0xFFL); |
| |
| return buffer; |
| } |
| |
| /** |
| * Deserializes the given long value. |
| * @param buffer A serialized long value. |
| * @return The deserialized long value. |
| */ |
| public static long deserializeLong(byte[] buffer) |
| { |
| Preconditions.checkArgument(buffer.length == Type.LONG.getByteSize()); |
| return deserializeLong(buffer, new MutableInt(0)); |
| } |
| |
| /** |
| * This method deserializes a double from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized double. |
| */ |
| public static double deserializeDouble(byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| long val = (((long)buffer[0 + offsetInt]) & 0xFFL) << 56 | |
| ((((long)buffer[1 + offsetInt]) & 0xFFL) << 48) | |
| ((((long)buffer[2 + offsetInt]) & 0xFFL) << 40) | |
| ((((long)buffer[3 + offsetInt]) & 0xFFL) << 32) | |
| ((((long)buffer[4 + offsetInt]) & 0xFFL) << 24) | |
| ((((long)buffer[5 + offsetInt]) & 0xFFL) << 16) | |
| ((((long)buffer[6 + offsetInt]) & 0xFFL) << 8) | |
| (((long)buffer[7 + offsetInt]) & 0xFFL); |
| |
| offset.add(Type.DOUBLE.getByteSize()); |
| return Double.longBitsToDouble(val); |
| } |
| |
| /** |
| * This method serializes the given double to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param valD The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeDouble(double valD, byte[] buffer, MutableInt offset) |
| { |
| long val = Double.doubleToLongBits(valD); |
| |
| int offsetInt = offset.intValue(); |
| buffer[0 + offsetInt] = (byte)((val >> 56) & 0xFFL); |
| buffer[1 + offsetInt] = (byte)((val >> 48) & 0xFFL); |
| buffer[2 + offsetInt] = (byte)((val >> 40) & 0xFFL); |
| buffer[3 + offsetInt] = (byte)((val >> 32) & 0xFFL); |
| buffer[4 + offsetInt] = (byte)((val >> 24) & 0xFFL); |
| buffer[5 + offsetInt] = (byte)((val >> 16) & 0xFFL); |
| buffer[6 + offsetInt] = (byte)((val >> 8) & 0xFFL); |
| buffer[7 + offsetInt] = (byte)(val & 0xFFL); |
| |
| offset.add(Type.DOUBLE.getByteSize()); |
| } |
| |
| public static byte[] serializeDouble(double valD) |
| { |
| byte[] buffer = new byte[Type.DOUBLE.getByteSize()]; |
| long val = Double.doubleToLongBits(valD); |
| |
| buffer[0] = (byte)((val >> 56) & 0xFFL); |
| buffer[1] = (byte)((val >> 48) & 0xFFL); |
| buffer[2] = (byte)((val >> 40) & 0xFFL); |
| buffer[3] = (byte)((val >> 32) & 0xFFL); |
| buffer[4] = (byte)((val >> 24) & 0xFFL); |
| buffer[5] = (byte)((val >> 16) & 0xFFL); |
| buffer[6] = (byte)((val >> 8) & 0xFFL); |
| buffer[7] = (byte)(val & 0xFFL); |
| |
| return buffer; |
| } |
| |
| /** |
| * This method deserializes an integer from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized integer. |
| */ |
| public static int deserializeInt(byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| int val = ((((int)buffer[0 + offsetInt]) & 0xFF) << 24) | |
| ((((int)buffer[1 + offsetInt]) & 0xFF) << 16) | |
| ((((int)buffer[2 + offsetInt]) & 0xFF) << 8) | |
| (((int)buffer[3 + offsetInt]) & 0xFF); |
| |
| offset.add(Type.INTEGER.getByteSize()); |
| return val; |
| } |
| |
| /** |
| * Deserializes the given serialized integer. |
| * @param buffer The integer value to deserialized. |
| * @return The deserialized integer value. |
| */ |
| public static int deserializeInt(byte[] buffer) |
| { |
| Preconditions.checkArgument(buffer.length == Type.INTEGER.getByteSize()); |
| return deserializeInt(buffer, new MutableInt(0)); |
| } |
| |
| /** |
| * This method serializes the given integer to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeInt(int val, byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| buffer[0 + offsetInt] = (byte)((val >> 24) & 0xFF); |
| buffer[1 + offsetInt] = (byte)((val >> 16) & 0xFF); |
| buffer[2 + offsetInt] = (byte)((val >> 8) & 0xFF); |
| buffer[3 + offsetInt] = (byte)(val & 0xFF); |
| |
| offset.add(Type.INTEGER.getByteSize()); |
| } |
| |
| /** |
| * Serializes the given integer value. |
| * @param val The value to serialize. |
| * @return The serialized integer value. |
| */ |
| public static byte[] serializeInt(int val) |
| { |
| byte[] buffer = new byte[Type.INTEGER.getByteSize()]; |
| |
| buffer[0] = (byte)((val >> 24) & 0xFF); |
| buffer[1] = (byte)((val >> 16) & 0xFF); |
| buffer[2] = (byte)((val >> 8) & 0xFF); |
| buffer[3] = (byte)(val & 0xFF); |
| |
| return buffer; |
| } |
| |
| /** |
| * This method deserializes a float from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized float. |
| */ |
| public static float deserializeFloat(byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| int val = ((((int)buffer[0 + offsetInt]) & 0xFF) << 24) | |
| ((((int)buffer[1 + offsetInt]) & 0xFF) << 16) | |
| ((((int)buffer[2 + offsetInt]) & 0xFF) << 8) | |
| (((int)buffer[3 + offsetInt]) & 0xFF); |
| |
| offset.add(Type.FLOAT.getByteSize()); |
| return Float.intBitsToFloat(val); |
| } |
| |
| /** |
| * This method serializes the given float to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param valf The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeFloat(float valf, byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| int val = Float.floatToIntBits(valf); |
| |
| buffer[0 + offsetInt] = (byte)((val >> 24) & 0xFF); |
| buffer[1 + offsetInt] = (byte)((val >> 16) & 0xFF); |
| buffer[2 + offsetInt] = (byte)((val >> 8) & 0xFF); |
| buffer[3 + offsetInt] = (byte)(val & 0xFF); |
| |
| offset.add(Type.FLOAT.getByteSize()); |
| } |
| |
| public static byte[] serializeFloat(float valf) |
| { |
| byte[] buffer = new byte[Type.FLOAT.getByteSize()]; |
| int val = Float.floatToIntBits(valf); |
| |
| buffer[0] = (byte)((val >> 24) & 0xFF); |
| buffer[1] = (byte)((val >> 16) & 0xFF); |
| buffer[2] = (byte)((val >> 8) & 0xFF); |
| buffer[3] = (byte)(val & 0xFF); |
| |
| return buffer; |
| } |
| |
| /** |
| * This method deserializes a short from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized short. |
| */ |
| public static short deserializeShort(byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| short val = (short)(((((int)buffer[0 + offsetInt]) & 0xFF) << 8) | |
| (((int)buffer[1 + offsetInt]) & 0xFF)); |
| |
| offset.add(Type.SHORT.getByteSize()); |
| return val; |
| } |
| |
| /** |
| * This method serializes the given short to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeShort(short val, byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| buffer[0 + offsetInt] = (byte)((val >> 8) & 0xFF); |
| buffer[1 + offsetInt] = (byte)(val & 0xFF); |
| |
| offset.add(Type.SHORT.getByteSize()); |
| } |
| |
| public static byte[] serializeShort(short val) |
| { |
| byte[] buffer = new byte[Type.SHORT.getByteSize()]; |
| |
| buffer[0] = (byte)((val >> 8) & 0xFF); |
| buffer[1] = (byte)(val & 0xFF); |
| |
| return buffer; |
| } |
| |
| /** |
| * This method deserializes a byte from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized byte. |
| */ |
| public static byte deserializeByte(byte[] buffer, MutableInt offset) |
| { |
| byte val = buffer[offset.intValue()]; |
| |
| offset.add(Type.BYTE.getByteSize()); |
| return val; |
| } |
| |
| |
| /** |
| * This method serializes the given byte to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeByte(byte val, byte[] buffer, MutableInt offset) |
| { |
| buffer[offset.intValue()] = val; |
| |
| offset.add(Type.BYTE.getByteSize()); |
| } |
| |
| public static byte[] serializeByte(byte val) |
| { |
| return new byte[]{val}; |
| } |
| |
| /** |
| * This method deserializes a boolean from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized boolean. |
| */ |
| public static boolean deserializeBoolean(byte[] buffer, MutableInt offset) |
| { |
| boolean val = buffer[offset.intValue()] != 0; |
| |
| offset.add(Type.BOOLEAN.getByteSize()); |
| return val; |
| } |
| |
| /** |
| * This method serializes the given boolean to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeBoolean(boolean val, byte[] buffer, MutableInt offset) |
| { |
| buffer[offset.intValue()] = (byte)(val ? 1 : 0); |
| |
| offset.add(Type.BOOLEAN.getByteSize()); |
| } |
| |
| public static byte[] serializeBoolean(boolean val) |
| { |
| return new byte[]{(byte)(val ? 1 : 0)}; |
| } |
| |
| /** |
| * This method deserializes a character from the given byte array from the given offset, |
| * and increments the offset appropriately. |
| * @param buffer The byte buffer to deserialize from. |
| * @param offset The offset to deserialize from. |
| * @return The deserialized character. |
| */ |
| public static char deserializeChar(byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| char val = (char)(((((int)buffer[0 + offsetInt]) & 0xFF) << 8) | |
| (((int)buffer[1 + offsetInt]) & 0xFF)); |
| |
| offset.add(Type.CHAR.getByteSize()); |
| return val; |
| } |
| |
| /** |
| * This method serializes the given character to the given byte buffer to the given offset, |
| * the method also increments the offset appropriately. |
| * @param val The value to serialize. |
| * @param buffer The byte buffer to serialize to. |
| * @param offset The offset in the buffer to serialize to and also to increment appropriately. |
| */ |
| public static void serializeChar(char val, byte[] buffer, MutableInt offset) |
| { |
| int offsetInt = offset.intValue(); |
| buffer[0 + offsetInt] = (byte)((val >> 8) & 0xFF); |
| buffer[1 + offsetInt] = (byte)(val & 0xFF); |
| |
| offset.add(Type.CHAR.getByteSize()); |
| } |
| |
| public static byte[] serializeChar(char val) |
| { |
| byte[] buffer = new byte[Type.CHAR.getByteSize()]; |
| |
| buffer[0] = (byte)((val >> 8) & 0xFF); |
| buffer[1] = (byte)(val & 0xFF); |
| |
| return buffer; |
| } |
| |
| /** |
| * Utility method for creating getters. This method is useful for creating a {@link GPOGetters} object |
| * which can be used to copy POJOs into GPOMutable objects. |
| * @param fields The fields to create getters for. The order of the fields in this list will be the same order |
| * that the getters will be returned in. |
| * @param valueToExpression A map from field names to the corresponding java expression to be used for getting |
| * the fields. |
| * @param clazz The Class of the POJO to extract values from. |
| * @param getterClazz The class of the getter object to create. |
| * @param getterMethodClazz The class of the getter method. |
| * @return An array of boolean getters for given fields. |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T> T[] createGetters(List<String> fields, Map<String, String> valueToExpression, |
| Class<?> clazz, Class<?> getterClazz, Class<?> getterMethodClazz) |
| { |
| @SuppressWarnings("unchecked") |
| T[] getters = (T[])Array.newInstance(getterMethodClazz, fields.size()); |
| |
| for (int getterIndex = 0; getterIndex < fields.size(); getterIndex++) { |
| String field = fields.get(getterIndex); |
| getters[getterIndex] = (T)PojoUtils.constructGetter(clazz, valueToExpression.get(field), getterClazz); |
| } |
| |
| return getters; |
| } |
| |
| /** |
| * Utility method for creating getters. This method is useful for creating a {@link GPOGetters} object |
| * which can be used to copy POJOs into GPOMutable objects. |
| * @param fields The fields to create getters for. The order of the fields in this list will be the same order |
| * that the getters will be returned in. |
| * @param valueToExpression A map from field names to the corresponding java expression to be used for getting |
| * the fields. |
| * @param clazz The Class of the POJO to extract values from. |
| * @return An array of boolean getters for given fields. |
| */ |
| public static Getter<Object, String>[] createGettersString(List<String> fields, Map<String, String> valueToExpression, |
| Class<?> clazz) |
| { |
| @SuppressWarnings({"unchecked","rawtypes"}) |
| Getter<Object, String>[] getters = new Getter[fields.size()]; |
| |
| for (int getterIndex = 0; getterIndex < fields.size(); getterIndex++) { |
| String field = fields.get(getterIndex); |
| getters[getterIndex] = PojoUtils.createGetter(clazz, valueToExpression.get(field), String.class); |
| } |
| |
| return getters; |
| } |
| |
| /** |
| * Utility method for creating getters. This method is useful for creating a {@link GPOGetters} object |
| * which can be used to copy POJOs into GPOMutable objects. |
| * @param fields The fields to create getters for. The order of the fields in this list will be the same order |
| * that the getters will be returned in. |
| * @param valueToExpression A map from field names to the corresponding java expression to be used for getting |
| * the fields. |
| * @param clazz The Class of the POJO to extract values from. |
| * @return An array of boolean getters for given fields. |
| */ |
| public static Getter<Object, Object>[] createGettersObject(List<String> fields, Map<String, String> valueToExpression, |
| Class<?> clazz) |
| { |
| @SuppressWarnings({"unchecked","rawtypes"}) |
| Getter<Object, Object>[] getters = new Getter[fields.size()]; |
| |
| for (int getterIndex = 0; getterIndex < fields.size(); getterIndex++) { |
| String field = fields.get(getterIndex); |
| getters[getterIndex] = PojoUtils.createGetter(clazz, valueToExpression.get(field), Object.class); |
| } |
| |
| return getters; |
| } |
| |
| /** |
| * This is a utility method which builds a {@link GPOGetters} object corresponding to the given {@link FieldsDescriptor}. |
| * This utility method is helpful for converting POJOs into GPOMutable objects. |
| * @param fieldToGetter A map whose keys are field names and whose values correspond to java getter expressions. Field names |
| * in this map should be the same as field names in the provided {@link FieldsDescriptor} object. |
| * @param fieldsDescriptor A {@link FieldsDescriptor} object which describes the type name and order of fields. |
| * @param clazz The Class of the POJO that the getters will be applied to. |
| * @return The {@link GPOGetters} object which can be used to convert POJOs into {@link GPOMutable} objects initialized |
| * with the same {@link FieldsDescriptor} object. |
| */ |
| public static GPOGetters buildGPOGetters(Map<String, String> fieldToGetter, FieldsDescriptor fieldsDescriptor, |
| Class<?> clazz) |
| { |
| GPOGetters gpoGetters = new GPOGetters(); |
| Map<Type, List<String>> typeToFields = fieldsDescriptor.getTypeToFields(); |
| |
| for (Map.Entry<Type, List<String>> entry : typeToFields.entrySet()) { |
| Type inputType = entry.getKey(); |
| GPOType gpoType = GPOType.GPO_TYPE_ARRAY[inputType.ordinal()]; |
| List<String> fields = entry.getValue(); |
| gpoType.buildGPOGetters(gpoGetters, fields, fieldToGetter, clazz); |
| } |
| |
| return gpoGetters; |
| } |
| |
| /** |
| * This is a utility method for converting a POJO to a {@link GPOMutable} object. This method assumes that the provided |
| * GPOMutable is initialized with the correct {@link FieldsDescriptor}, and that the given {@link GPOGetters} object has getters |
| * specified in the same order as fields in the {@link GPOMutable} object. |
| * @param mutable The {@link GPOMutable} object to copy POJO values into. It is assumed this object is initialized with |
| * the correct {@link FieldsDescriptor}. |
| * @param getters The getters to use when retrieving values from the provided POJO. It is assumed that the getters are |
| * specified in the same order as their corresponding fields in the {@link GPOMutable} object. |
| * @param object The POJO to extract values from. |
| */ |
| public static void copyPOJOToGPO(GPOMutable mutable, GPOGetters getters, Object object) |
| { |
| { |
| boolean[] tempBools = mutable.getFieldsBoolean(); |
| GetterBoolean<Object>[] tempGetterBools = getters.gettersBoolean; |
| |
| if (tempBools != null) { |
| for (int index = 0; index < tempBools.length; index++) { |
| tempBools[index] = tempGetterBools[index].get(object); |
| } |
| } |
| } |
| |
| { |
| byte[] tempBytes = mutable.getFieldsByte(); |
| GetterByte<Object>[] tempGetterByte = getters.gettersByte; |
| |
| if (tempBytes != null) { |
| for (int index = 0; index < tempBytes.length; index++) { |
| tempBytes[index] = tempGetterByte[index].get(object); |
| } |
| } |
| } |
| |
| { |
| char[] tempChar = mutable.getFieldsCharacter(); |
| GetterChar<Object>[] tempGetterChar = getters.gettersChar; |
| |
| if (tempChar != null) { |
| for (int index = 0; index < tempChar.length; index++) { |
| tempChar[index] = tempGetterChar[index].get(object); |
| } |
| } |
| } |
| |
| { |
| double[] tempDouble = mutable.getFieldsDouble(); |
| GetterDouble<Object>[] tempGetterDouble = getters.gettersDouble; |
| |
| if (tempDouble != null) { |
| for (int index = 0; index < tempDouble.length; index++) { |
| tempDouble[index] = tempGetterDouble[index].get(object); |
| } |
| } |
| } |
| |
| { |
| float[] tempFloat = mutable.getFieldsFloat(); |
| GetterFloat<Object>[] tempGetterFloat = getters.gettersFloat; |
| |
| if (tempFloat != null) { |
| for (int index = 0; index < tempFloat.length; index++) { |
| tempFloat[index] = tempGetterFloat[index].get(object); |
| } |
| } |
| } |
| |
| { |
| int[] tempInt = mutable.getFieldsInteger(); |
| GetterInt<Object>[] tempGetterInt = getters.gettersInteger; |
| |
| if (tempInt != null) { |
| for (int index = 0; index < tempInt.length; index++) { |
| tempInt[index] = tempGetterInt[index].get(object); |
| } |
| } |
| } |
| |
| { |
| long[] tempLong = mutable.getFieldsLong(); |
| GetterLong<Object>[] tempGetterLong = getters.gettersLong; |
| |
| if (tempLong != null) { |
| for (int index = 0; index < tempLong.length; index++) { |
| tempLong[index] = tempGetterLong[index].get(object); |
| } |
| } |
| } |
| |
| { |
| short[] tempShort = mutable.getFieldsShort(); |
| GetterShort<Object>[] tempGetterShort = getters.gettersShort; |
| |
| if (tempShort != null) { |
| for (int index = 0; index < tempShort.length; index++) { |
| tempShort[index] = tempGetterShort[index].get(object); |
| } |
| } |
| } |
| |
| { |
| String[] tempString = mutable.getFieldsString(); |
| Getter<Object, String>[] tempGetterString = getters.gettersString; |
| |
| if (tempString != null) { |
| for (int index = 0; index < tempString.length; index++) { |
| tempString[index] = tempGetterString[index].get(object); |
| } |
| } |
| } |
| } |
| |
| public static void indirectCopy(GPOMutable dest, GPOMutable src, IndexSubset indexSubset) |
| { |
| { |
| String[] destString = dest.getFieldsString(); |
| String[] srcString = src.getFieldsString(); |
| int[] srcIndex = indexSubset.fieldsStringIndexSubset; |
| if (destString != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destString[index] = srcString[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| boolean[] destBoolean = dest.getFieldsBoolean(); |
| boolean[] srcBoolean = src.getFieldsBoolean(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (destBoolean != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destBoolean[index] = srcBoolean[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| char[] destChar = dest.getFieldsCharacter(); |
| char[] srcChar = src.getFieldsCharacter(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (destChar != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destChar[index] = srcChar[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| byte[] destByte = dest.getFieldsByte(); |
| byte[] srcByte = src.getFieldsByte(); |
| int[] srcIndex = indexSubset.fieldsByteIndexSubset; |
| if (destByte != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destByte[index] = srcByte[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| short[] destShort = dest.getFieldsShort(); |
| short[] srcShort = src.getFieldsShort(); |
| int[] srcIndex = indexSubset.fieldsShortIndexSubset; |
| if (destShort != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destShort[index] = srcShort[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| int[] destInteger = dest.getFieldsInteger(); |
| int[] srcInteger = src.getFieldsInteger(); |
| int[] srcIndex = indexSubset.fieldsIntegerIndexSubset; |
| if (destInteger != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destInteger[index] = srcInteger[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| long[] destLong = dest.getFieldsLong(); |
| long[] srcLong = src.getFieldsLong(); |
| int[] srcIndex = indexSubset.fieldsLongIndexSubset; |
| if (destLong != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| |
| destLong[index] = srcLong[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| float[] destFloat = dest.getFieldsFloat(); |
| float[] srcFloat = src.getFieldsFloat(); |
| int[] srcIndex = indexSubset.fieldsFloatIndexSubset; |
| if (destFloat != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destFloat[index] = srcFloat[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| double[] destDouble = dest.getFieldsDouble(); |
| double[] srcDouble = src.getFieldsDouble(); |
| int[] srcIndex = indexSubset.fieldsDoubleIndexSubset; |
| if (destDouble != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destDouble[index] = srcDouble[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| Object[] destObject = dest.getFieldsObject(); |
| Object[] srcObject = src.getFieldsObject(); |
| int[] srcIndex = indexSubset.fieldsObjectIndexSubset; |
| if (destObject != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| destObject[index] = srcObject[srcIndex[index]]; |
| } |
| } |
| } |
| } |
| |
| public static int hashcode(GPOMutable gpo) |
| { |
| int hashCode = 0; |
| |
| { |
| String[] stringArray = gpo.getFieldsString(); |
| if (stringArray != null) { |
| for (int index = 0; index < stringArray.length; index++) { |
| hashCode ^= stringArray[index].hashCode(); |
| } |
| } |
| } |
| |
| { |
| boolean[] booleanArray = gpo.getFieldsBoolean(); |
| if (booleanArray != null) { |
| for (int index = 0; index < booleanArray.length; index++) { |
| hashCode ^= booleanArray[index] ? 1 : 0; |
| } |
| } |
| } |
| |
| { |
| char[] charArray = gpo.getFieldsCharacter(); |
| if (charArray != null) { |
| for (int index = 0; index < charArray.length; index++) { |
| hashCode ^= Character.getNumericValue(charArray[index]); |
| } |
| } |
| } |
| |
| { |
| byte[] byteArray = gpo.getFieldsByte(); |
| if (byteArray != null) { |
| for (int index = 0; index < byteArray.length; index++) { |
| hashCode ^= byteArray[index]; |
| } |
| } |
| } |
| |
| { |
| short[] shortArray = gpo.getFieldsShort(); |
| if (shortArray != null) { |
| for (int index = 0; index < shortArray.length; index++) { |
| hashCode ^= shortArray[index]; |
| } |
| } |
| } |
| |
| { |
| int[] integerArray = gpo.getFieldsInteger(); |
| if (integerArray != null) { |
| for (int index = 0; index < integerArray.length; index++) { |
| hashCode ^= integerArray[index]; |
| } |
| } |
| } |
| |
| { |
| long[] longArray = gpo.getFieldsLong(); |
| if (longArray != null) { |
| for (int index = 0; index < longArray.length; index++) { |
| hashCode ^= longArray[index]; |
| } |
| } |
| } |
| |
| { |
| float[] floatArray = gpo.getFieldsFloat(); |
| if (floatArray != null) { |
| for (int index = 0; index < floatArray.length; index++) { |
| hashCode ^= Float.floatToIntBits(floatArray[index]); |
| } |
| } |
| } |
| |
| { |
| double[] doubleArray = gpo.getFieldsDouble(); |
| if (doubleArray != null) { |
| for (int index = 0; index < doubleArray.length; index++) { |
| hashCode ^= Double.doubleToLongBits(doubleArray[index]); |
| } |
| } |
| } |
| |
| { |
| Object[] objectArray = gpo.getFieldsObject(); |
| if (objectArray != null) { |
| for (int index = 0; index < objectArray.length; index++) { |
| hashCode ^= objectArray[index].hashCode(); |
| } |
| } |
| } |
| |
| return hashCode; |
| } |
| |
| /** |
| * This function computes the hashcode of a {@link GPOMutable} based on a specified subset of its data. |
| * <br/> |
| * <br/> |
| * <b>Note:</b> In some cases a {@link GPOMutable} object contains a field which is bucketed. In the case of |
| * bucketed fields, you may want to preserve the original value of the field, but only use the bucketed value |
| * of the field for computing a hashcode. In order to do this you can store the original value of {@link GPOMutable}'s |
| * field before calling this function, and replace it with the bucketed value. Then after the hashcode is computed, the |
| * original value of the field can be restored. |
| * |
| * @param gpo The {@link GPOMutable} to compute a hashcode for. |
| * @param indexSubset The subset of the {@link GPOMutable} used to compute the hashcode. |
| * @return The hashcode for the given {@link GPOMutable} computed from the specified subset of its data. |
| */ |
| public static int indirectHashcode(GPOMutable gpo, IndexSubset indexSubset) |
| { |
| int hashCode = 7; |
| final int hashMultiplier = 23; |
| |
| { |
| String[] stringArray = gpo.getFieldsString(); |
| int[] srcIndex = indexSubset.fieldsStringIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + stringArray[srcIndex[index]].hashCode(); |
| } |
| } |
| } |
| |
| { |
| boolean[] booleanArray = gpo.getFieldsBoolean(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + (booleanArray[srcIndex[index]] ? 1 : 0); |
| } |
| } |
| } |
| |
| { |
| char[] charArray = gpo.getFieldsCharacter(); |
| int[] srcIndex = indexSubset.fieldsCharacterIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + Character.getNumericValue(charArray[srcIndex[index]]); |
| } |
| } |
| } |
| |
| { |
| byte[] byteArray = gpo.getFieldsByte(); |
| int[] srcIndex = indexSubset.fieldsByteIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + byteArray[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| short[] shortArray = gpo.getFieldsShort(); |
| int[] srcIndex = indexSubset.fieldsShortIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + shortArray[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| int[] integerArray = gpo.getFieldsInteger(); |
| int[] srcIndex = indexSubset.fieldsIntegerIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + integerArray[srcIndex[index]]; |
| } |
| } |
| } |
| |
| { |
| long[] longArray = gpo.getFieldsLong(); |
| int[] srcIndex = indexSubset.fieldsLongIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| long element = longArray[srcIndex[index]]; |
| int elementHash = (int)(element ^ (element >>> 32)); |
| hashCode = hashMultiplier * hashCode + elementHash; |
| } |
| } |
| } |
| |
| { |
| float[] floatArray = gpo.getFieldsFloat(); |
| int[] srcIndex = indexSubset.fieldsFloatIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| hashCode = hashMultiplier * hashCode + Float.floatToIntBits(floatArray[srcIndex[index]]); |
| } |
| } |
| } |
| |
| { |
| double[] doubleArray = gpo.getFieldsDouble(); |
| int[] srcIndex = indexSubset.fieldsDoubleIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| long element = Double.doubleToLongBits(doubleArray[srcIndex[index]]); |
| int elementHash = (int)(element ^ (element >>> 32)); |
| hashCode = hashMultiplier * hashCode + elementHash; |
| } |
| } |
| } |
| |
| { |
| Object[] objectArray = gpo.getFieldsObject(); |
| int[] srcIndex = indexSubset.fieldsObjectIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| |
| hashCode = hashMultiplier * hashCode + objectArray[srcIndex[index]].hashCode(); |
| } |
| } |
| } |
| |
| return hashCode; |
| } |
| |
| public static boolean equals(GPOMutable dest, GPOMutable src) |
| { |
| { |
| String[] destString = dest.getFieldsString(); |
| String[] srcString = src.getFieldsString(); |
| if (destString != null) { |
| for (int index = 0; index < srcString.length; index++) { |
| if (!destString[index].equals(srcString[index])) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| boolean[] destBoolean = dest.getFieldsBoolean(); |
| boolean[] srcBoolean = src.getFieldsBoolean(); |
| if (destBoolean != null) { |
| for (int index = 0; index < srcBoolean.length; index++) { |
| if (destBoolean[index] != srcBoolean[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| char[] destChar = dest.getFieldsCharacter(); |
| char[] srcChar = src.getFieldsCharacter(); |
| if (destChar != null) { |
| for (int index = 0; index < srcChar.length; index++) { |
| if (destChar[index] != srcChar[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| byte[] destByte = dest.getFieldsByte(); |
| byte[] srcByte = src.getFieldsByte(); |
| if (destByte != null) { |
| for (int index = 0; index < srcByte.length; index++) { |
| if (destByte[index] != srcByte[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| short[] destShort = dest.getFieldsShort(); |
| short[] srcShort = src.getFieldsShort(); |
| if (destShort != null) { |
| for (int index = 0; index < srcShort.length; index++) { |
| if (destShort[index] != srcShort[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| int[] destInteger = dest.getFieldsInteger(); |
| int[] srcInteger = src.getFieldsInteger(); |
| if (destInteger != null) { |
| for (int index = 0; index < srcInteger.length; index++) { |
| if (destInteger[index] != srcInteger[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| long[] destLong = dest.getFieldsLong(); |
| long[] srcLong = src.getFieldsLong(); |
| if (destLong != null) { |
| for (int index = 0; index < srcLong.length; index++) { |
| if (destLong[index] != srcLong[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| float[] destFloat = dest.getFieldsFloat(); |
| float[] srcFloat = src.getFieldsFloat(); |
| if (destFloat != null) { |
| for (int index = 0; index < srcFloat.length; index++) { |
| if (destFloat[index] != srcFloat[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| double[] destDouble = dest.getFieldsDouble(); |
| double[] srcDouble = src.getFieldsDouble(); |
| if (destDouble != null) { |
| for (int index = 0; index < srcDouble.length; index++) { |
| if (destDouble[index] != srcDouble[index]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| Object[] destObject = dest.getFieldsObject(); |
| Object[] srcObject = src.getFieldsObject(); |
| if (destObject != null) { |
| for (int index = 0; index < srcObject.length; index++) { |
| if (!destObject[index].equals(srcObject[index])) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| public static boolean subsetEquals(GPOMutable dest, GPOMutable src, IndexSubset indexSubset) |
| { |
| { |
| String[] destString = dest.getFieldsString(); |
| String[] srcString = src.getFieldsString(); |
| int[] srcIndex = indexSubset.fieldsStringIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (!destString[srcIndex[index]].equals(srcString[srcIndex[index]])) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| boolean[] destBoolean = dest.getFieldsBoolean(); |
| boolean[] srcBoolean = src.getFieldsBoolean(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destBoolean[srcIndex[index]] != srcBoolean[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| char[] destChar = dest.getFieldsCharacter(); |
| char[] srcChar = src.getFieldsCharacter(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destChar[srcIndex[index]] != srcChar[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| byte[] destByte = dest.getFieldsByte(); |
| byte[] srcByte = src.getFieldsByte(); |
| int[] srcIndex = indexSubset.fieldsByteIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destByte[srcIndex[index]] != srcByte[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| short[] destShort = dest.getFieldsShort(); |
| short[] srcShort = src.getFieldsShort(); |
| int[] srcIndex = indexSubset.fieldsShortIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destShort[srcIndex[index]] != srcShort[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| int[] destInteger = dest.getFieldsInteger(); |
| int[] srcInteger = src.getFieldsInteger(); |
| int[] srcIndex = indexSubset.fieldsIntegerIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destInteger[srcIndex[index]] != srcInteger[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| long[] destLong = dest.getFieldsLong(); |
| long[] srcLong = src.getFieldsLong(); |
| int[] srcIndex = indexSubset.fieldsLongIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destLong[srcIndex[index]] != srcLong[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| float[] destFloat = dest.getFieldsFloat(); |
| float[] srcFloat = src.getFieldsFloat(); |
| int[] srcIndex = indexSubset.fieldsFloatIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destFloat[srcIndex[index]] != srcFloat[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| double[] destDouble = dest.getFieldsDouble(); |
| double[] srcDouble = src.getFieldsDouble(); |
| int[] srcIndex = indexSubset.fieldsDoubleIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destDouble[srcIndex[index]] != srcDouble[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| Object[] destObject = dest.getFieldsObject(); |
| Object[] srcObject = src.getFieldsObject(); |
| int[] srcIndex = indexSubset.fieldsObjectIndexSubset; |
| if (srcIndex != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (!destObject[srcIndex[index]].equals(srcObject[srcIndex[index]])) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| public static boolean indirectEquals(GPOMutable dest, GPOMutable src, IndexSubset indexSubset) |
| { |
| { |
| String[] destString = dest.getFieldsString(); |
| String[] srcString = src.getFieldsString(); |
| int[] srcIndex = indexSubset.fieldsStringIndexSubset; |
| if (destString != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (!destString[index].equals(srcString[srcIndex[index]])) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| boolean[] destBoolean = dest.getFieldsBoolean(); |
| boolean[] srcBoolean = src.getFieldsBoolean(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (destBoolean != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destBoolean[index] != srcBoolean[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| char[] destChar = dest.getFieldsCharacter(); |
| char[] srcChar = src.getFieldsCharacter(); |
| int[] srcIndex = indexSubset.fieldsBooleanIndexSubset; |
| if (destChar != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destChar[index] != srcChar[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| byte[] destByte = dest.getFieldsByte(); |
| byte[] srcByte = src.getFieldsByte(); |
| int[] srcIndex = indexSubset.fieldsByteIndexSubset; |
| if (destByte != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destByte[index] != srcByte[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| short[] destShort = dest.getFieldsShort(); |
| short[] srcShort = src.getFieldsShort(); |
| int[] srcIndex = indexSubset.fieldsShortIndexSubset; |
| if (destShort != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destShort[index] != srcShort[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| int[] destInteger = dest.getFieldsInteger(); |
| int[] srcInteger = src.getFieldsInteger(); |
| int[] srcIndex = indexSubset.fieldsIntegerIndexSubset; |
| if (destInteger != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destInteger[index] != srcInteger[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| long[] destLong = dest.getFieldsLong(); |
| long[] srcLong = src.getFieldsLong(); |
| int[] srcIndex = indexSubset.fieldsLongIndexSubset; |
| if (destLong != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destLong[index] != srcLong[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| float[] destFloat = dest.getFieldsFloat(); |
| float[] srcFloat = src.getFieldsFloat(); |
| int[] srcIndex = indexSubset.fieldsFloatIndexSubset; |
| if (destFloat != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destFloat[index] != srcFloat[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| double[] destDouble = dest.getFieldsDouble(); |
| double[] srcDouble = src.getFieldsDouble(); |
| int[] srcIndex = indexSubset.fieldsDoubleIndexSubset; |
| if (destDouble != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (destDouble[index] != srcDouble[srcIndex[index]]) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| { |
| Object[] destObject = dest.getFieldsObject(); |
| Object[] srcObject = src.getFieldsObject(); |
| int[] srcIndex = indexSubset.fieldsObjectIndexSubset; |
| if (destObject != null) { |
| for (int index = 0; index < srcIndex.length; index++) { |
| if (srcIndex[index] == -1) { |
| continue; |
| } |
| if (!destObject[index].equals(srcObject[srcIndex[index]])) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| public static void zeroFillNumeric(GPOMutable value) |
| { |
| if (value.getFieldsByte() != null) { |
| Arrays.fill(value.getFieldsByte(), (byte)0); |
| } |
| |
| if (value.getFieldsShort() != null) { |
| Arrays.fill(value.getFieldsShort(), (short)0); |
| } |
| |
| if (value.getFieldsInteger() != null) { |
| Arrays.fill(value.getFieldsInteger(), 0); |
| } |
| |
| if (value.getFieldsLong() != null) { |
| Arrays.fill(value.getFieldsLong(), 0L); |
| } |
| |
| if (value.getFieldsFloat() != null) { |
| Arrays.fill(value.getFieldsFloat(), 0.0f); |
| } |
| |
| if (value.getFieldsDouble() != null) { |
| Arrays.fill(value.getFieldsDouble(), 0.0); |
| } |
| } |
| |
| public static IndexSubset computeSubIndices(FieldsDescriptor child, FieldsDescriptor parent) |
| { |
| IndexSubset indexSubset = new IndexSubset(); |
| |
| for (Map.Entry<Type, List<String>> entry : child.getTypeToFields().entrySet()) { |
| Type type = entry.getKey(); |
| List<String> childFields = entry.getValue(); |
| List<String> parentFields = parent.getTypeToFields().get(type); |
| |
| int size = child.getTypeToSize().get(type); |
| int[] indices; |
| if (child.getTypeToFields().get(type) != null && |
| child.getCompressedTypes().contains(type)) { |
| indices = new int[1]; |
| } else { |
| indices = new int[size]; |
| |
| for (int index = 0; index < size; index++) { |
| if (parentFields == null) { |
| indices[index] = -1; |
| } else { |
| indices[index] = parentFields.indexOf(childFields.get(index)); |
| } |
| } |
| } |
| |
| switch (type) { |
| case BOOLEAN: { |
| indexSubset.fieldsBooleanIndexSubset = indices; |
| break; |
| } |
| case CHAR: { |
| indexSubset.fieldsCharacterIndexSubset = indices; |
| break; |
| } |
| case STRING: { |
| indexSubset.fieldsStringIndexSubset = indices; |
| break; |
| } |
| case BYTE: { |
| indexSubset.fieldsByteIndexSubset = indices; |
| break; |
| } |
| case SHORT: { |
| indexSubset.fieldsShortIndexSubset = indices; |
| break; |
| } |
| case INTEGER: { |
| indexSubset.fieldsIntegerIndexSubset = indices; |
| break; |
| } |
| case LONG: { |
| indexSubset.fieldsLongIndexSubset = indices; |
| break; |
| } |
| case FLOAT: { |
| indexSubset.fieldsFloatIndexSubset = indices; |
| break; |
| } |
| case DOUBLE: { |
| indexSubset.fieldsDoubleIndexSubset = indices; |
| break; |
| } |
| default: { |
| throw new UnsupportedOperationException("Type " + type); |
| } |
| } |
| } |
| |
| return indexSubset; |
| } |
| |
| /** |
| * This object is used to define the subset of data contained in a {@link GPOMutable} |
| * object that we are interested in. |
| */ |
| public static class IndexSubset implements Serializable |
| { |
| private static final long serialVersionUID = 201506251015L; |
| |
| /** |
| * Index of boolean fields of interest. Null if there are no boolean fields of interest. |
| */ |
| public int[] fieldsBooleanIndexSubset; |
| /** |
| * Index of character fields of interest. Null if there are no character fields of interest. |
| */ |
| public int[] fieldsCharacterIndexSubset; |
| /** |
| * Index of byte fields of interest. Null if there are no byte fields of interest. |
| */ |
| public int[] fieldsByteIndexSubset; |
| /** |
| * Index of short fields of interest. Null if there are no short fields of interest. |
| */ |
| public int[] fieldsShortIndexSubset; |
| /** |
| * Index of integer fields of interest. Null if there are no integer fields of interest. |
| */ |
| public int[] fieldsIntegerIndexSubset; |
| /** |
| * Index of long fields of interest. Null if there are no long fields of interest. |
| */ |
| public int[] fieldsLongIndexSubset; |
| /** |
| * Index of float fields of interest. Null if there are no float fields of interest. |
| */ |
| public int[] fieldsFloatIndexSubset; |
| /** |
| * Index of double fields of interest. Null if there are no double fields of interest. |
| */ |
| public int[] fieldsDoubleIndexSubset; |
| /** |
| * Index of String fields of interest. Null if there are no String fields of interest. |
| */ |
| public int[] fieldsStringIndexSubset; |
| /** |
| * Index of Object fields of interest. Null if there are no Object fields of interest. |
| */ |
| public int[] fieldsObjectIndexSubset; |
| |
| public IndexSubset() |
| { |
| //Do nothing |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "IndexSubset{" + "fieldsBooleanIndexSubset=" + fieldsBooleanIndexSubset + ", fieldsCharacterIndexSubset=" |
| + fieldsCharacterIndexSubset + ", fieldsByteIndexSubset=" + fieldsByteIndexSubset |
| + ", fieldsShortIndexSubset=" + fieldsShortIndexSubset + ", fieldsIntegerIndexSubset=" |
| + fieldsIntegerIndexSubset + ", fieldsLongIndexSubset=" + fieldsLongIndexSubset + ", fieldsFloatIndexSubset=" |
| + fieldsFloatIndexSubset + ", fieldsDoubleIndexSubset=" + fieldsDoubleIndexSubset |
| + ", fieldsStringIndexSubset=" + fieldsStringIndexSubset + '}'; |
| } |
| } |
| |
| public static Map<String, Object> getDestringedData(FieldsDescriptor fd, Map<String, String> stringMap) |
| { |
| Map<String, Object> fieldToData = Maps.newHashMap(); |
| Map<String, Type> fieldToType = fd.getFieldToType(); |
| |
| for (Map.Entry<String, String> entry : stringMap.entrySet()) { |
| Object objValue; |
| String valueString = entry.getValue(); |
| Type valueType = fieldToType.get(entry.getKey()); |
| |
| switch (valueType) { |
| case BOOLEAN: { |
| objValue = Boolean.valueOf(valueString); |
| break; |
| } |
| case BYTE: |
| { |
| objValue = Byte.valueOf(valueString); |
| break; |
| } |
| case SHORT: |
| { |
| objValue = Short.valueOf(valueString); |
| break; |
| } |
| case INTEGER: |
| { |
| objValue = Integer.valueOf(valueString); |
| break; |
| } |
| case LONG: |
| { |
| objValue = Long.valueOf(valueString); |
| break; |
| } |
| case FLOAT: |
| { |
| objValue = Float.valueOf(valueString); |
| break; |
| } |
| case DOUBLE: |
| { |
| objValue = Double.valueOf(valueString); |
| break; |
| } |
| case STRING: |
| { |
| objValue = valueString; |
| break; |
| } |
| case OBJECT: |
| throw new UnsupportedOperationException("The given type " + entry.getValue() + " is unsupported."); |
| default: |
| throw new UnsupportedOperationException("The given type " + entry.getValue() + " is unsupported."); |
| } |
| |
| fieldToData.put(entry.getKey(), objValue); |
| } |
| |
| return fieldToData; |
| } |
| |
| public static Map<String, Object> convertToMapIntersection(GPOMutable gpo, Fields fields) |
| { |
| Map<String, Object> values = Maps.newHashMap(); |
| |
| for (String field : fields.getFields()) { |
| if (!gpo.getFieldDescriptor().getFields().getFields().contains(field)) { |
| continue; |
| } |
| |
| Object valueObj = gpo.getField(field); |
| values.put(field, valueObj); |
| } |
| |
| return values; |
| } |
| |
| /** |
| * Determines if the given value is within the range of the specified type. |
| * @param type The type to determine the range of. Valid types can be byte or short. |
| * @param val The value to check the range of. |
| * @return True if the given int value is within the range of the specified type, false otherwise. |
| */ |
| public static boolean insideRange(Type type, int val) |
| { |
| switch (type) { |
| case BYTE: { |
| return !(val < (int)Byte.MIN_VALUE || val > (int)Byte.MAX_VALUE); |
| } |
| case SHORT: { |
| return !(val < (int)Short.MIN_VALUE || val > (int)Short.MAX_VALUE); |
| } |
| default: |
| throw new UnsupportedOperationException("This operation is not supported for the type " + type); |
| } |
| } |
| |
| /** |
| * Returns true if the given type is of type byte, short, or integer. |
| * @param type The type to check. |
| * @return True if the given type is of type byte, short or integer. |
| */ |
| public static boolean numericTypeIntOrSmaller(Type type) |
| { |
| return type == Type.BYTE || type == Type.SHORT || type == Type.INTEGER; |
| } |
| } |