/* * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package kr.debop4j.core.tools; import kr.debop4j.core.BinaryStringFormat; import kr.debop4j.core.ISerializer; import kr.debop4j.core.io.BinarySerializer; import kr.debop4j.core.parallelism.AsyncTool; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.Callable; import java.util.concurrent.Future; import static kr.debop4j.core.Guard.shouldNotBeNull; import static kr.debop4j.core.tools.StringTool.getBytesFromHexString; import static kr.debop4j.core.tools.StringTool.getStringFromBytes; /** * {@link ISerializer} 를 이용한 직렬화/역직렬화를 수행하는 Utility Method 를 제공합니다. * * @author 배성혁 ( sunghyouk.bae@gmail.com ) * @since 12. 9. 14 */ @Slf4j public final class SerializeTool { @Getter(lazy = true) private static final BinarySerializer binarySerializer = new BinarySerializer(); private SerializeTool() { } /** * 객체를 직렬화하여 문자열로 반환합니다. * * @param serializer the serializer * @param graph the graph * @return the string */ public static String serializeAsString(ISerializer serializer, Object graph) { shouldNotBeNull(serializer, "serializer"); if (graph == null) return StringTool.EMPTY_STR; return getStringFromBytes(serializer.serialize(graph), BinaryStringFormat.HexDecimal); } /** * 직렬화된 문자열을 역직렬화하여, 객체로 빌드합니다. * * @param serializer the serializer * @param clazz the clazz * @param serializedStr the serialized str * @return the 객체 */ public static <T> T deserializeFromString(final ISerializer serializer, final Class<T> clazz, final String serializedStr) { shouldNotBeNull(serializer, "serializer"); if (StringTool.isEmpty(serializedStr)) { return null; } return serializer.deserialize(getBytesFromHexString(serializedStr), clazz); } /** * 객체를 직렬화하여 {@link java.io.OutputStream} 으로 변환합니다. * * @param serializer the serializer * @param graph the graph * @return the output stream * @throws IOException the iO exception */ public static OutputStream serializeAsStream(final ISerializer serializer, Object graph) throws IOException { shouldNotBeNull(serializer, "serializer"); if (graph == null) { return new ByteArrayOutputStream(); } return StreamTool.toOutputStream(serializer.serialize(graph)); } /** * {@link java.io.InputStream} 을 읽어 역직렬화하여, 객체를 빌드합니다. @param serializer the serializer * * @param clazz the clazz * @param inputStream the input stream * @return the t * @throws IOException the iO exception */ public static <T> T deserializeFromStream(ISerializer serializer, Class<T> clazz, InputStream inputStream) throws IOException { shouldNotBeNull(serializer, "serializer"); if (inputStream == null) return null; return serializer.deserialize(StreamTool.toByteArray(inputStream), clazz); } /** * 지정된 객체를 직렬화하여, byte[] 로 변환합니다. * * @param graph 직렬화 대상 객체 * @return 직렬화된 정보 */ public static byte[] serializeObject(Object graph) { return getBinarySerializer().serialize(graph); } /** * 직렬화된 byte[] 정보를 역직렬화하여, 객체로 변환합니다. * * @param bytes 직렬화된 정보 * @param clazz the clazz * @return 역직렬화된 객체 */ public static <T> T deserializeObject(byte[] bytes, Class<T> clazz) { return getBinarySerializer().deserialize(bytes, clazz); } /** * 객체를 {@link BinarySerializer} 를 이용하여 deep copy 를 수행합니다. @param graph the graph * * @return the t */ @SuppressWarnings("unchecked") public static <T> T copyObject(T graph) { if (graph == null) return null; return (T) deserializeObject(serializeObject(graph), graph.getClass()); } /** * 비동기 방식으로 객체를 직렬화합니다. * * @param graph 객체 * @return 직렬화 결과 */ public static Future<byte[]> serializeObjectAsync(final Object graph) { if (graph == null) { return AsyncTool.getTaskHasResult(new byte[0]); } return AsyncTool.startNew(new Callable<byte[]>() { @Override public byte[] call() throws Exception { return getBinarySerializer().serialize(graph); } }); } /** * 직렬화한 정보를 역직렬화하여 객체로 변환합니다. * * @param bytes 직렬화된 정보 * @param clazz 역직렬화할 객체의 수형 * @return 역직렬화한 객체 */ public static <T> Future<T> deserializeObjectAsync(final byte[] bytes, final Class<T> clazz) { if (ArrayTool.isEmpty(bytes)) { return null; } return AsyncTool.startNew(new Callable<T>() { @Override public T call() throws Exception { return getBinarySerializer().deserialize(bytes, clazz); } }); } /** * 객체를 비동기 방식으로 복사합니다. * * @param graph 원본 인스턴스 * @return 복사한 인스턴스 */ @SuppressWarnings("unchecked") public static <T> Future<T> copyObjectAsync(final T graph) { if (graph == null) { return AsyncTool.getTaskHasResult(graph); } return AsyncTool.startNew(new Callable<T>() { @Override public T call() throws Exception { byte[] bytes = getBinarySerializer().serialize(graph); return (T) getBinarySerializer().deserialize(bytes, graph.getClass()); } }); } }