Package org.codehaus.preon

Source Code of org.codehaus.preon.Codecs

/**
* Copyright (C) 2009-2010 Wilfred Springer
*
* This file is part of Preon.
*
* Preon is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* Preon 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Preon; see the file COPYING. If not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Linking this library statically or dynamically with other modules is making a
* combined work based on this library. Thus, the terms and conditions of the
* GNU General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent modules, and
* to copy and distribute the resulting executable under terms of your choice,
* provided that you also meet, for each linked independent module, the terms
* and conditions of the license of that module. An independent module is a
* module which is not derived from or based on this library. If you modify this
* library, you may extend this exception to your version of the library, but
* you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package org.codehaus.preon;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import javax.xml.stream.XMLStreamException;

import nl.flotsam.pecia.builder.ArticleDocument;
import nl.flotsam.pecia.builder.base.DefaultArticleDocument;
import nl.flotsam.pecia.builder.base.DefaultDocumentBuilder;
import nl.flotsam.pecia.builder.html.HtmlDocumentBuilder;
import nl.flotsam.pecia.builder.xml.StreamingXmlWriter;
import nl.flotsam.pecia.builder.xml.XmlWriter;
import org.codehaus.preon.binding.BindingDecorator;
import org.codehaus.preon.buffer.BitBuffer;
import org.codehaus.preon.buffer.DefaultBitBuffer;
import org.codehaus.preon.channel.BitChannel;
import org.codehaus.preon.channel.OutputStreamBitChannel;

import org.apache.commons.io.IOUtils;

import com.ctc.wstx.stax.WstxOutputFactory;

/**
* A utility class, providing some convenience mechanisms for using and documenting {@link Codec Codecs}.
*
* @author Wilfred Springer
*/
public class Codecs {

    private static final Builder DEFAULT_BUILDER = new DefaultBuilder();


    /**
     * An enumeration of potential documentation types.
     *
     * @see Codecs#document(Codec, org.codehaus.preon.Codecs.DocumentType, File)
     * @see Codecs#document(Codec, org.codehaus.preon.Codecs.DocumentType, OutputStream)
     */
    public enum DocumentType {

        Html {

            @Override
            public DefaultDocumentBuilder createDocumentBuilder(XmlWriter writer) {
                return new HtmlDocumentBuilder(writer, this.getClass()
                        .getResource("/default.css")) {

                };
            }
        };

        /**
         * Returns a {@link DefaultDocumentBuilder} instance for the given type of document.
         *
         * @param writer The {@link XmlWriter} to which the document will be written.
         * @return A {@link DefaultDocumentBuilder} capable of rendering the desired document format.
         */
        public abstract DefaultDocumentBuilder createDocumentBuilder(
                XmlWriter writer);

    }

    /**
     * Documents the codec, writing a document of the given type to the given file.
     *
     * @param <T>   The type of objects decoded by the {@link Codec}.
     * @param codec The actual codec.
     * @param type  The type of document type of the document generated.
     * @param file  The file to which all output needs to be written.
     * @throws FileNotFoundException If the file cannot be written.
     */
    public static <T> void document(Codec<T> codec, DocumentType type, File file)
            throws FileNotFoundException {
        OutputStream out = null;
        try {
            out = new FileOutputStream(file);
            document(codec, type, out);
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * Documents the codec, writing a document of the given type to the given {@link OutputStream}.
     *
     * @param <T>   The type of objects decoded by the {@link Codec}.
     * @param codec The actual codec.
     * @param type  The type of document type of the document generated.
     * @param out   The {@link OutputStream} receiving the document.
     */
    public static <T> void document(Codec<T> codec, DocumentType type,
                                    OutputStream out) {
        WstxOutputFactory documentFactory = new WstxOutputFactory();
        XmlWriter writer;
        try {
            writer = new StreamingXmlWriter(documentFactory
                    .createXMLStreamWriter(out));
            DefaultDocumentBuilder builder = type.createDocumentBuilder(writer);
            ArticleDocument document = new DefaultArticleDocument(builder,
                    codec.getCodecDescriptor().getTitle());
            document(codec, document);
            document.end();
        } catch (XMLStreamException e) {
            // In the unlikely event this happens:
            throw new RuntimeException("Failed to create stream writer.");
        }
    }

    /**
     * Documents the codec, writing contents to the {@link ArticleDocument} passed in.
     *
     * @param <T>      The type of objects decoded by the {@link Codec}.
     * @param codec    The actual codec.
     * @param document The document in which the documentation of the Codec needs to be generated.
     */
    public static <T> void document(Codec<T> codec, ArticleDocument document) {
        CodecDescriptor descriptor = codec.getCodecDescriptor();
        if (descriptor.requiresDedicatedSection()) {
            document.document(descriptor.details("buffer"));
        } else {
            document.para().text("Full description missing.").end();
        }
    }

    /**
     * Decodes an object from the buffer passed in.
     *
     * @param <T>    The of object to be decoded.
     * @param codec  The {@link Codec} that will take care of the actual work.
     * @param buffer An array of bytes holding the encoded data.
     * @return The decoded object.
     * @throws DecodingException If the {@link Codec} fails to decode a value from the buffer passed in.
     */
    public static <T> T decode(Codec<T> codec, byte... buffer)
            throws DecodingException {
        return decode(codec, ByteBuffer.wrap(buffer));
    }

    public static <T> T decode(Codec<T> codec, Builder builder, byte... buffer)
            throws DecodingException {
        return decode(codec, ByteBuffer.wrap(buffer), builder);
    }

    /**
     * Decodes an object from the buffer passed in.
     *
     * @param <T>    The of object to be decoded.
     * @param codec  The {@link Codec} that will take care of the actual work.
     * @param buffer An array of bytes holding the encoded data.
     * @return The decoded object.
     * @throws DecodingException If the {@link Codec} fails to decode a value from the buffer passed in.
     */
    public static <T> T decode(Codec<T> codec, ByteBuffer buffer)
            throws DecodingException {
        return decode(codec, new DefaultBitBuffer(buffer), null, null);
    }

    public static <T> T decode(Codec<T> codec, ByteBuffer buffer, Builder builder)
            throws DecodingException {
        return decode(codec, new DefaultBitBuffer(buffer), builder, null);
    }

    public static <T> T decode(Codec<T> codec, BitBuffer buffer, Builder builder, Resolver resolver)
            throws DecodingException {
        if (builder == null) {
            builder = DEFAULT_BUILDER;
        }
        return codec.decode(buffer, resolver, builder);
    }

    /**
     * Decodes an object from the buffer passed in.
     *
     * @param <T>   The of object to be decoded.
     * @param codec The {@link Codec} that will take care of the actual work.
     * @param file  The {@link File} providing the data to be decoded.
     * @return The decoded object.
     * @throws FileNotFoundException If the {@link File} does not exist.
     * @throws IOException           If the system fails to read data from the file.
     * @throws DecodingException     If the {@link Codec} fails to decode a value from the buffer passed in.
     */
    public static <T> T decode(Codec<T> codec, File file)
            throws FileNotFoundException, IOException, DecodingException {
        return decode(codec, null, file);
    }

    public static <T> T decode(Codec<T> codec, Builder builder, File file)
            throws FileNotFoundException, IOException, DecodingException {
        FileInputStream in = null;
        FileChannel channel = null;
        try {
            in = new FileInputStream(file);
            channel = in.getChannel();
            int fileSize = (int) channel.size();
            ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0,
                    fileSize);
            return decode(codec, buffer, builder);
        } finally {
            if (channel != null) {
                channel.close();
            }
        }
    }

    /**
     * Encodes the value to the channel passed in, using the given Codec. So why not have this operation on codec
     * instead? Well, it <em>is</em> actually there. However, there will be quite a few overloaded versions of this
     * operation, and Java would force you to implement these operations on <em>every Codec</em>. That's not a very
     * attractive objection. So instead of inheritance, it's all delegation now.
     *
     * @param value   The object that needs to be encoded.
     * @param codec   The codec to be used.
     * @param channel The target {@link org.codehaus.preon.channel.BitChannel}.
     * @param <T>     The type of object to be encoded.
     * @throws IOException If the {@link org.codehaus.preon.channel.BitChannel} no longer receives the data.
     */
    public static <T> void encode(T value, Codec<T> codec, BitChannel channel) throws IOException {
        codec.encode(value, channel, new NullResolver());
    }

    public static <T> byte[] encode(T value, Codec<T> codec) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        encode(value, codec, out);
        return out.toByteArray();
    }

    public static <T> void encode(T value, Codec<T> codec, OutputStream out) throws IOException {
        encode(value, codec, new OutputStreamBitChannel(out));
    }

    /**
     * Creates a {@link Codec} for the given type.
     *
     * @param <T>  The of object constructed using the {@link Codec}.
     * @param type The type of object constructed using the {@link Codec}.
     * @return A {@link Codec} capable of decoding/encoding instances of the type passed in.
     */
    public static <T> Codec<T> create(Class<T> type) {
        return new DefaultCodecFactory().create(type);
    }

    /**
     * Creates a {@link Codec} for the given type, accepting an number of {@link CodecFactory CodecFactories} to be taken
     * into account while constructing the {@link Codec}.
     *
     * @param <T>       The of object constructed using the {@link Codec}.
     * @param type      The type of object constructed using the {@link Codec}.
     * @param factories Additional {@link CodecFactory CodecFactories} to be used while constructing the {@link Codec}.
     * @return A {@link Codec} capable of decoding instances of the type passed in.
     */
    public static <T> Codec<T> create(Class<T> type, CodecFactory... factories) {
        return create(type, factories, new CodecDecorator[0]);
    }

    /**
     * Creates a {@link Codec} for the given type, accepting an number of {@link CodecDecorator CodecDecorators} to be
     * taken into account while constructing the {@link Codec}.
     *
     * @param <T>        The type of object constructed using the {@link Codec}.
     * @param decorators Additional {@link CodecDecorator CodecDecorators} to be used while constructing the {@link
     *                   Codec}.
     * @return A {@link Codec} capable of decoding instances of the type passed in, taking the {@link CodecDecorator
     *         CodecDecorators} into account.
     */
    public static <T> Codec<T> create(Class<T> type,
                                      CodecDecorator... decorators) {
        return create(type, new CodecFactory[0], decorators);
    }

    /**
     * Creates a {@link Codec} for the given type, accepting an number of {@link CodecDecorator CodecDecorators} to be
     * taken into account while constructing the {@link Codec}.
     *
     * @param <T>        The type of object constructed using the {@link Codec}.
     * @param factories  Additional {@link CodecFactory CodecFactories} to be used while constructing the {@link Codec}.
     * @param decorators Additional {@link CodecDecorator CodecDecorators} to be used while constructing the {@link
     *                   Codec}.
     * @return A {@link Codec} capable of decoding instances of the type passed in, taking the {@link CodecDecorator
     *         CodecDecorators} into account.
     */
  public static <T> Codec<T> create(Class<T> type, CodecFactory[] factories,
      CodecDecorator[] decorators) {
        return create(type, factories, decorators, new BindingDecorator[0]);
  }

    public static <T> Codec<T> create(Class<T> type, CodecFactory[] factories,
            CodecDecorator[] decorators, BindingDecorator[] bindingDecorators) {
        return new DefaultCodecFactory().create(null, type,
                factories, decorators, bindingDecorators);
    }

}
TOP

Related Classes of org.codehaus.preon.Codecs

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.