blob: 88eaeaf09169e8d6ab0ff398d2072f92c6eca31a [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.ignite.internal.processors.cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.internal.binary.BinaryArray;
import org.apache.ignite.internal.binary.BinaryUtils;
import org.apache.ignite.internal.util.MutableSingletonList;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
/**
* Cache object utility methods.
*/
public class CacheObjectUtils {
/**
* @param o Object to unwrap.
* @param keepBinary Keep binary flag.
* @param cpy Copy value flag.
* @return Unwrapped object.
*/
public static Object unwrapBinaryIfNeeded(CacheObjectValueContext ctx, CacheObject o, boolean keepBinary, boolean cpy) {
return unwrapBinary(ctx, o, keepBinary, cpy, null);
}
/**
* @param ctx Cache object context.
* @param o Object to unwrap.
* @param keepBinary Keep binary flag.
* @param cpy Copy value flag.
* @param ldr Class loader, used for deserialization from binary representation.
* @return Unwrapped object.
*/
public static Object unwrapBinaryIfNeeded(
CacheObjectValueContext ctx,
Object o,
boolean keepBinary,
boolean cpy,
@Nullable ClassLoader ldr
) {
if (o == null)
return null;
// TODO has to be overloaded
if (o instanceof Map.Entry) {
Map.Entry entry = (Map.Entry)o;
Object key = entry.getKey();
Object uKey = unwrapBinary(ctx, key, keepBinary, cpy, ldr);
Object val = entry.getValue();
Object uVal = unwrapBinary(ctx, val, keepBinary, cpy, ldr);
return (key != uKey || val != uVal) ? F.t(uKey, uVal) : o;
}
return unwrapBinary(ctx, o, keepBinary, cpy, ldr);
}
/**
* @param col Collection of objects to unwrap.
* @param keepBinary Keep binary flag.
* @return Unwrapped collection.
*/
public static Collection<Object> unwrapBinariesIfNeeded(CacheObjectValueContext ctx, Collection<?> col,
boolean keepBinary) {
return unwrapBinariesIfNeeded(ctx, col, keepBinary, true);
}
/**
* @param col Collection to unwrap.
* @param keepBinary Keep binary flag.
* @param cpy Copy flag.
* @return Unwrapped collection.
*/
private static Collection<Object> unwrapKnownCollection(CacheObjectValueContext ctx, Collection<?> col,
boolean keepBinary, boolean cpy) {
Collection<Object> col0 = BinaryUtils.newKnownCollection(col);
assert col0 != null;
for (Object obj : col)
col0.add(unwrapBinary(ctx, obj, keepBinary, cpy, null));
return (col0 instanceof MutableSingletonList) ? U.convertToSingletonList(col0) : col0;
}
/**
* Unwraps map.
*
* @param map Map to unwrap.
* @param keepBinary Keep binary flag.
* @return Unwrapped collection.
*/
private static Map<Object, Object> unwrapBinariesIfNeeded(CacheObjectValueContext ctx, Map<Object, Object> map,
boolean keepBinary, boolean cpy) {
if (keepBinary)
return map;
Map<Object, Object> map0 = BinaryUtils.newMap(map);
for (Map.Entry<Object, Object> e : map.entrySet())
// TODO why don't we use keepBinary parameter here?
map0.put(
unwrapBinary(ctx, e.getKey(), false, cpy, null),
unwrapBinary(ctx, e.getValue(), false, cpy, null));
return map0;
}
/**
* @param col Collection to unwrap.
* @param keepBinary Keep binary flag.
* @param cpy Copy value flag.
* @return Unwrapped collection.
*/
private static Collection<Object> unwrapBinariesIfNeeded(CacheObjectValueContext ctx, Collection<?> col,
boolean keepBinary, boolean cpy) {
Collection<Object> col0 = BinaryUtils.newKnownCollection(col);
if (col0 == null)
col0 = new ArrayList<>(col.size());
for (Object obj : col)
col0.add(unwrapBinaryIfNeeded(ctx, obj, keepBinary, cpy, null));
return col0;
}
/**
* Unwrap array of binaries if needed.
*
* @param arr Array.
* @param keepBinary Keep binary flag.
* @param cpy Copy.
* @return Result.
*/
private static Object[] unwrapBinariesInArrayIfNeeded(CacheObjectValueContext ctx, Object[] arr, boolean keepBinary,
boolean cpy) {
if (BinaryUtils.knownArray(arr))
return arr;
Object[] res = new Object[arr.length];
for (int i = 0; i < arr.length; i++)
res[i] = unwrapBinary(ctx, arr[i], keepBinary, cpy, null);
return res;
}
/**
* Unwraps an object for end user.
*
* @param ctx Cache object context.
* @param o Object to unwrap.
* @param keepBinary False when need to deserialize object from a binary one, true otherwise.
* @param cpy True means the object will be copied before return, false otherwise.
* @param ldr Class loader, used for deserialization from binary representation.
* @return Unwrapped object.
*/
public static Object unwrapBinary(
CacheObjectValueContext ctx,
Object o,
boolean keepBinary,
boolean cpy,
@Nullable ClassLoader ldr
) {
if (o == null)
return o;
while (BinaryUtils.knownCacheObject(o)) {
CacheObject co = (CacheObject)o;
if (!co.isPlatformType() && keepBinary)
return o;
// It may be a collection of binaries
o = co.value(ctx, cpy, ldr);
}
if (BinaryUtils.knownCollection(o))
return unwrapKnownCollection(ctx, (Collection<Object>)o, keepBinary, cpy);
else if (BinaryUtils.knownMap(o))
return unwrapBinariesIfNeeded(ctx, (Map<Object, Object>)o, keepBinary, cpy);
else if (o instanceof Object[] && !BinaryArray.useBinaryArrays())
return unwrapBinariesInArrayIfNeeded(ctx, (Object[])o, keepBinary, cpy);
else if (o instanceof BinaryArray && !keepBinary)
return ((BinaryObject)o).deserialize(ldr);
return o;
}
/**
* Private constructor.
*/
private CacheObjectUtils() {
// No-op.
}
}