FileSinkSWF.java

/*
 * Copyright 2006 - 2013
 *     Stefan Balev     <stefan.balev@graphstream-project.org>
 *     Julien Baudry    <julien.baudry@graphstream-project.org>
 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
 *     Yoann Pign��      <yoann.pigne@graphstream-project.org>
 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
 * 
 * This file is part of GraphStream <http://graphstream-project.org>.
 * 
 * GraphStream is a library whose purpose is to handle static or dynamic
 * graph, create them from scratch, file or any source and display them.
 * 
 * This program is free software distributed under the terms of two licenses, the
 * CeCILL-C license that fits European law, and the GNU Lesser General Public
 * License. You can  use, modify and/ or redistribute the software under the terms
 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
 */
package org.graphstream.stream.file;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;

import org.graphstream.graph.Graph;

/**
 * This class intends to output a dynamic graph into a Flash animation.
 * 
 * <p>
 * <b>This work may never to any usable feature. Please do not try to use it or
 * ask for help about it.</b>
 * </p>
 */
public class FileSinkSWF implements FileSink {
	private static class BitString {
		/**
		 * Bit 0 mask.
		 **/
		protected static final byte BIT_0 = (byte) Integer.parseInt("10000000",
				2);
		/**
		 * Bit 1 mask.
		 **/
		protected static final byte BIT_1 = (byte) Integer.parseInt("01000000",
				2);
		/**
		 * Bit 2 mask.
		 **/
		protected static final byte BIT_2 = (byte) Integer.parseInt("00100000",
				2);
		/**
		 * Bit 3 mask.
		 **/
		protected static final byte BIT_3 = (byte) Integer.parseInt("00010000",
				2);
		/**
		 * Bit 4 mask.
		 **/
		protected static final byte BIT_4 = (byte) Integer.parseInt("00001000",
				2);
		/**
		 * Bit 5 mask.
		 **/
		protected static final byte BIT_5 = (byte) Integer.parseInt("00000100",
				2);
		/**
		 * Bit 6 mask.
		 **/
		protected static final byte BIT_6 = (byte) Integer.parseInt("00000010",
				2);
		/**
		 * Bit 7 mask.
		 **/
		protected static final byte BIT_7 = (byte) Integer.parseInt("00000001",
				2);
		/**
		 * Set of all masks.
		 **/
		protected static final byte[] BITS = { BIT_0, BIT_1, BIT_2, BIT_3,
				BIT_4, BIT_5, BIT_6, BIT_7 };

		/**
		 * Buffer storing data.
		 * 
		 * @see java.nio.ByteBuffer
		 **/
		protected ByteBuffer buffer;
		/**
		 * Size of the buffer, current pointers.
		 **/
		private int size, curseur, bitCurseur;

		BitString(int... values) {
			this.size = this.curseur = this.bitCurseur = 0;

			int bitsize = 0;

			for (int i = 0; i < values.length; i++)
				bitsize = Math.max(bitsize,
						Integer.toBinaryString(Math.abs(values[i])).length());

			int totalbits = 5 + values.length * (bitsize + 1);

			__resize(totalbits / 8 + (totalbits % 8 == 0 ? 0 : 1));
			fill(false);

			String sizeBinary = Integer.toBinaryString(bitsize + 1);
			for (int i = sizeBinary.length() - 1; i > Math.max(0,
					sizeBinary.length() - 6); i--)
				add(sizeBinary.charAt(i) != '0');
			for (int i = sizeBinary.length(); i < 5; i++)
				add(false);

			String valueBinary;
			for (int i = 0; i < values.length; i++) {
				add(values[i] < 0);
				valueBinary = Integer.toBinaryString(Math.abs(values[i]));

				for (int j = 0; j < bitsize; j++) {
					if (j < valueBinary.length())
						add(valueBinary.charAt(bitsize - 1 - j) != '0');
					else
						add(values[i] < 0);
				}
			}
		}

		/**
		 * Resize the string.
		 * 
		 * @param size
		 *            in bytes new size
		 **/
		private void __resize(int size) {
			ByteBuffer nBuffer = ByteBuffer.allocate(size);

			for (int i = 0; i < Math.min(this.size, size); i++)
				nBuffer.put(buffer.get(i));

			this.buffer = nBuffer;
			this.size = size;
		}

		/**
		 * Bit value at the given index.
		 * 
		 * @param index
		 *            bit index
		 **/
		public boolean valueAt(int index) {
			return (buffer.get(index / 8) & BITS[index % 8]) != 0;
		}

		/**
		 * Add a bit.
		 * 
		 * @param value
		 *            bit value
		 **/
		public void add(boolean value) {
			if (curseur >= size) {
				__resize(size + 1);
			}

			if (value) {
				byte val = buffer.get(curseur);
				val = (byte) (val | (1 << (7 - bitCurseur)));
				buffer.put(curseur, val);
			}

			bitCurseur++;

			if (bitCurseur > 7) {
				bitCurseur = 0;
				curseur++;
			}
		}

		/**
		 * Fill with the given value.
		 */
		public void fill(boolean v) {
			fill(v, 0, size * 8);
		}

		public void fill(boolean v, int offset, int size) {
			for (int i = offset; i < offset + size; i++) {
				setValue(i, v);
			}
		}

		public void setValue(int id, boolean v) {
			byte val = buffer.get(id / 8);

			if (v) {
				val = (byte) (val | (1 << (7 - (id % 8))));
			} else {
				val = (byte) (val & (~(1 << (7 - (id % 8)))));
			}

			buffer.put(id / 8, val);
		}

		/**
		 * BitString to string.
		 **/
		@Override
		public String toString() {
			StringBuffer b = new StringBuffer();
			for (int i = 0; i < curseur; i++) {
				for (int j = 0; j < 8; j++)
					b.append(valueAt(i * 8 + j) ? '1' : '0');
			}
			for (int i = 0; i < bitCurseur; i++)
				b.append(valueAt(curseur * 8 + i) ? '1' : '0');
			return b.toString();
		}
	}

	private final static int BUFFER_SIZE = 1024000;

	private final static byte F = 0x46;
	private final static byte W = 0x57;
	private final static byte S = 0x53;
	private final static byte VERSION = 0x0A;

	ByteBuffer buffer;
	FileChannel channel;

	long position;
	long currentSize;

	@SuppressWarnings("unused")
	private void initChannelAndBuffer(String path) {
		if (channel != null)
			closeCurrentChannel();

		try {
			RandomAccessFile file = new RandomAccessFile(path, "rw");

			channel = file.getChannel();
			buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
			buffer.order(ByteOrder.LITTLE_ENDIAN);

			position = 0;
			currentSize = 0;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	private void closeCurrentChannel() {

	}

	@SuppressWarnings("unused")
	private void writeHeader() {
		buffer.put(F);
		buffer.put(W);
		buffer.put(S);
		buffer.put(VERSION);
		buffer.putInt(0);
		writeRECT(buffer, 0, 0, 0, 0);
		buffer.putShort((short) 0);
	}

	private static void writeRECT(ByteBuffer buffer, int xmin, int xmax,
			int ymin, int ymax) {
		writeSingleBits(buffer, xmin, xmax, ymin, ymax);
	}

	private static void writeSingleBits(ByteBuffer buffer, int... values) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < values.length; i++)
			max = Math.max(max, Math.abs(values[i]));

	}

	public void begin(String fileName) throws IOException {
		// TODO Auto-generated method stub

	}

	public void begin(OutputStream stream) throws IOException {
		// TODO Auto-generated method stub

	}

	public void begin(Writer writer) throws IOException {
		
	}
	
	public void end() throws IOException {
		// TODO Auto-generated method stub

	}

	public void flush() throws IOException {
		// TODO Auto-generated method stub

	}

	public void writeAll(Graph graph, String fileName) throws IOException {
		// TODO Auto-generated method stub

	}

	public void writeAll(Graph graph, OutputStream stream) throws IOException {
		// TODO Auto-generated method stub

	}

	public void writeAll(Graph graph, Writer writer) throws IOException {
		
	}
	
	public void edgeAttributeAdded(String graphId, long timeId, String edgeId,
			String attribute, Object value) {
		// TODO Auto-generated method stub

	}

	public void edgeAttributeChanged(String graphId, long timeId,
			String edgeId, String attribute, Object oldValue, Object newValue) {
		// TODO Auto-generated method stub

	}

	public void edgeAttributeRemoved(String graphId, long timeId,
			String edgeId, String attribute) {
		// TODO Auto-generated method stub

	}

	public void graphAttributeAdded(String graphId, long timeId,
			String attribute, Object value) {
		// TODO Auto-generated method stub

	}

	public void graphAttributeChanged(String graphId, long timeId,
			String attribute, Object oldValue, Object newValue) {
		// TODO Auto-generated method stub

	}

	public void graphAttributeRemoved(String graphId, long timeId,
			String attribute) {
		// TODO Auto-generated method stub

	}

	public void nodeAttributeAdded(String graphId, long timeId, String nodeId,
			String attribute, Object value) {
		// TODO Auto-generated method stub

	}

	public void nodeAttributeChanged(String graphId, long timeId,
			String nodeId, String attribute, Object oldValue, Object newValue) {
		// TODO Auto-generated method stub

	}

	public void nodeAttributeRemoved(String graphId, long timeId,
			String nodeId, String attribute) {
		// TODO Auto-generated method stub

	}

	public void edgeAdded(String graphId, long timeId, String edgeId,
			String fromNodeId, String toNodeId, boolean directed) {
		// TODO Auto-generated method stub

	}

	public void edgeRemoved(String graphId, long timeId, String edgeId) {
		// TODO Auto-generated method stub

	}

	public void graphCleared(String graphId, long timeId) {
		// TODO Auto-generated method stub

	}

	public void nodeAdded(String graphId, long timeId, String nodeId) {
		// TODO Auto-generated method stub

	}

	public void nodeRemoved(String graphId, long timeId, String nodeId) {
		// TODO Auto-generated method stub

	}

	public void stepBegins(String graphId, long timeId, double time) {
		// TODO Auto-generated method stub

	}

	public static void main(String[] args) {
		BitString bs = new BitString(1024, -1024);
		System.out.println(bs);
	}
}