/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program 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 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package com.bc.ceres.binio; import com.bc.ceres.binio.internal.DataContextImpl; import com.bc.ceres.binio.util.FileChannelIOHandler; import com.bc.ceres.binio.util.RandomAccessFileIOHandler; import com.bc.ceres.core.Assert; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; /** * A binary data format. */ public class DataFormat { private CompoundType type; private DataFormat basisFormat; private String name; private String version; private ByteOrder byteOrder; private final Map<String, Type> typeDefMap; public DataFormat() { this.typeDefMap = new HashMap<String, Type>(16); } public DataFormat(CompoundType type) { this(type, ByteOrder.BIG_ENDIAN); } public DataFormat(CompoundType type, ByteOrder byteOrder) { setType(type); setName(type.getName()); setVersion("1.0.0"); setByteOrder(byteOrder); this.typeDefMap = new HashMap<String, Type>(16); } /** * Creates a new random access file data context. * * @param file the file object * @param mode the access mode, one of <tt>"r"</tt>, <tt>"rw"</tt>, <tt>"rws"</tt>, or * <tt>"rwd"</tt>. See also mode description in {@link RandomAccessFile#RandomAccessFile(java.io.File, String)}. * @return The context. * @throws FileNotFoundException If in read-only mode and the file could nt be found. */ public DataContext createContext(File file, String mode) throws FileNotFoundException { Assert.notNull(file, "file"); Assert.notNull(mode, "mode"); final RandomAccessFile raf = new RandomAccessFile(file, mode); return new DataContextImpl(this, new RandomAccessFileIOHandler(raf)) { private boolean disposed; @Override public synchronized void dispose() { super.dispose(); disposed = true; try { raf.close(); } catch (IOException e) { // ignore } } @Override protected void finalize() throws Throwable { super.finalize(); if (!disposed) { dispose(); } } }; } public DataContext createContext(RandomAccessFile raf) { Assert.notNull(raf, "raf"); return new DataContextImpl(this, new RandomAccessFileIOHandler(raf)); } public DataContext createContext(FileChannel fileChannel) { Assert.notNull(fileChannel, "fileChannel"); return new DataContextImpl(this, new FileChannelIOHandler(fileChannel)); } public DataContext createContext(IOHandler ioHandler) { Assert.notNull(ioHandler, "ioHandler"); return new DataContextImpl(this, ioHandler); } public DataFormat getBasisFormat() { return basisFormat; } public void setBasisFormat(DataFormat basisFormat) { this.basisFormat = basisFormat; } public CompoundType getType() { return type; } public void setType(CompoundType type) { Assert.notNull(type, "type"); this.type = type; } public String getName() { return name; } public void setName(String name) { Assert.notNull(name, "name"); this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { Assert.notNull(version, "version"); this.version = version; } public ByteOrder getByteOrder() { return byteOrder; } public void setByteOrder(ByteOrder byteOrder) { Assert.notNull(byteOrder, "byteOrder"); this.byteOrder = byteOrder; } public boolean isTypeDef(String name) { Assert.notNull(name, "name"); return typeDefMap.containsKey(name) || (basisFormat != null && basisFormat.isTypeDef(name)); } public Type getTypeDef(String name) { Assert.notNull(name, "name"); Type type = typeDefMap.get(name); if (type == null) { type = basisFormat != null ? basisFormat.getTypeDef(name) : null; } if (type == null) { throw new IllegalArgumentException(MessageFormat.format("Type definition ''{0}'' not found", name)); } return type; } public void addTypeDef(String name, Type type) { Assert.notNull(name, "name"); Assert.notNull(type, "type"); Type oldType = typeDefMap.get(name); if (oldType != null && !oldType.equals(type)) { throw new IllegalArgumentException(MessageFormat.format("Type definition ''{0}'' already known as ''{1}''", name, oldType.getName())); } typeDefMap.put(name, type); } public Type removeTypeDef(String name) { Assert.notNull(name, "name"); return typeDefMap.remove(name); } }