/* --------------------------------------------------------------------- * Numenta Platform for Intelligent Computing (NuPIC) * Copyright (C) 2016, Numenta, Inc. Unless you have an agreement * with Numenta, Inc., for a separate license for this software code, the * following terms and conditions apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero Public License for more details. * * You should have received a copy of the GNU Affero Public License * along with this program. If not, see http://www.gnu.org/licenses. * * http://numenta.org/licenses/ * --------------------------------------------------------------------- */ package org.numenta.nupic.serialize; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import org.numenta.nupic.model.Persistable; import org.numenta.nupic.network.PersistenceAPI; import org.nustaq.serialization.FSTConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link PeristenceAPI} underbelly which uses the FST Fast Serialization library to * serialize various HTM.java object. * * @author cogmission * @see PersistenceAPI * @see SerialConfig */ public class SerializerCore implements Persistable { private static final long serialVersionUID = 1L; protected static final Logger LOGGER = LoggerFactory.getLogger(SerializerCore.class); private Class<?>[] classes; /** Use of Fast Serialize https://github.com/RuedigerMoeller/fast-serialization */ private transient FSTConfiguration fastSerialConfig = FSTConfiguration.createDefaultConfiguration(); /** * Constructs a new {@code SerializerCore}, registering the * specified classes to avoid extraneous writing of filenames to * the serialized stream. * * @param classes the class array of registered classes */ public SerializerCore(Class<?>...classes) { this.classes = classes; initFST(); } /** * Initializes the delegate serializer */ private void initFST() { fastSerialConfig = FSTConfiguration.createDefaultConfiguration(); if(classes != null) { fastSerialConfig.registerClass(classes); } } /** * Registers the specified classes which obviates the need to write class names * to the stream, saving processing time and space. * @param c an array of classes to register */ @SuppressWarnings("rawtypes") public void registerClass(Class... c) { fastSerialConfig.registerClass(c); } /** * Called by whatever serializable infrastructure would want to serialize this * {@code SerializerCore} * * @param in the stream containing this {@code SerializerCore} * @throws IOException as a result of io problems * @throws ClassNotFoundException if classes contained within the stream cannot be resolved */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); initFST(); } /** * Returns the specified {@link InputStream} wrapped in an HTM input stream * @param is the InputStream to wrap * @return the FSTObjectInput * @throws IOException */ public HTMObjectInput getObjectInput(InputStream is) throws IOException { return new HTMObjectInput(is, fastSerialConfig); } /** * Returns the specified {@link OutputStream} wrapped in an HTM output stream * @param is the OutputStream to wrap * @return the HTMObjectOutput */ public <T extends Persistable> HTMObjectOutput getObjectOutput(OutputStream os) { return new HTMObjectOutput(os, fastSerialConfig); } /** * Serializes the specified {@link Persistable} to a byte array * then returns it. * @param instance the instance of Persistable to serialize * @return the byte array */ public <T extends Persistable> byte[] serialize(T instance) { byte[] bytes = null; try { bytes = fastSerialConfig.asByteArray(instance); } catch(Exception e) { bytes = null; throw new RuntimeException(e); } return bytes; } /** * Deserializes the specified Class type from the specified byte array * * @param bytes the byte array containing the object to be deserialized * @return the deserialized object of type <T> */ @SuppressWarnings("unchecked") public <T extends Persistable> T deSerialize(byte[] bytes) { T retVal = (T)fastSerialConfig.asObject(bytes); return retVal.postDeSerialize(); } /** * For testing only! * @return */ FSTConfiguration getSerialScheme() { return fastSerialConfig; } }