MaterialLoader.java
/*
* Copyright (C) 2012 Alberto Irurueta Carro (alberto@irurueta.com)
*
* 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 com.irurueta.geometry.io;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Set;
/**
* Abstract class defining the interface for classes in charge of loading
* materials.
*/
public abstract class MaterialLoader implements Closeable {
/**
* Maximum allowed file size to keep cached in memory. Files exceeding this
* size will just be streamed.
*/
public static final long DEFAULT_FILE_SIZE_LIMIT_TO_KEEP_IN_MEMORY = 50000000;
/**
* Constant defining whether textures must be validated by default.
*/
public static final boolean DEFAULT_TEXTURE_VALIDATION_ENABLED = true;
/**
* Instance in charge of reading data from file.
*/
protected AbstractFileReaderAndWriter reader;
/**
* Boolean indicating that this instance is locked because decoding is being
* done.
*/
protected boolean locked;
/**
* Listener in charge of notifying when the decoding starts, ends or
* progress events.
*/
protected MaterialLoaderListener listener;
/**
* File to be read.
*/
protected File file;
/**
* Indicates if texture images must be validated to ensure that they are
* valid image files.
*/
protected boolean textureValidationEnabled;
/**
* Limit of bytes to keep mapped in memory. If provided file exceeds this
* value, then it is not mapped into memory.
*/
private long fileSizeLimitToKeepInMemory;
/**
* Default Constructor.
*/
protected MaterialLoader() {
fileSizeLimitToKeepInMemory = DEFAULT_FILE_SIZE_LIMIT_TO_KEEP_IN_MEMORY;
reader = null;
locked = false;
listener = null;
textureValidationEnabled = DEFAULT_TEXTURE_VALIDATION_ENABLED;
}
/**
* Constructor.
*
* @param f material file to be read.
* @throws IOException raised if provided file does not exist or an I/O
* exception occurs.
*/
protected MaterialLoader(final File f) throws IOException {
fileSizeLimitToKeepInMemory = DEFAULT_FILE_SIZE_LIMIT_TO_KEEP_IN_MEMORY;
file = f;
if (f.length() < fileSizeLimitToKeepInMemory) {
reader = new MappedFileReaderAndWriter(f, FileChannel.MapMode.READ_ONLY);
} else {
reader = new FileReaderAndWriter(f, FileChannel.MapMode.READ_ONLY);
}
locked = false;
listener = null;
textureValidationEnabled = DEFAULT_TEXTURE_VALIDATION_ENABLED;
}
/**
* Constructor.
*
* @param listener material listener to notify start, end and progress
* events.
*/
protected MaterialLoader(final MaterialLoaderListener listener) {
fileSizeLimitToKeepInMemory = DEFAULT_FILE_SIZE_LIMIT_TO_KEEP_IN_MEMORY;
reader = null;
locked = false;
this.listener = listener;
textureValidationEnabled = DEFAULT_TEXTURE_VALIDATION_ENABLED;
}
/**
* Constructor.
*
* @param f material file to be read.
* @param listener material listener to notify start, end and progress
* events.
* @throws IOException raised if provided file does not exist or an I/O
* exception occurs.
*/
protected MaterialLoader(final File f, final MaterialLoaderListener listener) throws IOException {
fileSizeLimitToKeepInMemory = DEFAULT_FILE_SIZE_LIMIT_TO_KEEP_IN_MEMORY;
file = f;
if (f.length() < fileSizeLimitToKeepInMemory) {
reader = new MappedFileReaderAndWriter(f, FileChannel.MapMode.READ_ONLY);
} else {
reader = new FileReaderAndWriter(f, FileChannel.MapMode.READ_ONLY);
}
locked = false;
this.listener = listener;
textureValidationEnabled = DEFAULT_TEXTURE_VALIDATION_ENABLED;
}
/**
* Returns maximum allowed file size to keep cached in memory. Files
* exceeding this size will just be streamed.
*
* @return maximum allowed file size to keep cached in memory.
*/
public long getFileSizeLimitToKeepInMemory() {
return fileSizeLimitToKeepInMemory;
}
/**
* Sets maximum allowed file size to keep cached in memory. Files exceeding
* this size will just be streamed.
*
* @param fileSizeLimitToKeepInMemory maximum allowed file size to keep
* cached in memory.
* @throws LockedException if this instance is already loading another file.
*/
public void setFileSizeLimitToKeepInMemory(final long fileSizeLimitToKeepInMemory) throws LockedException {
if (isLocked()) {
throw new LockedException();
}
this.fileSizeLimitToKeepInMemory = fileSizeLimitToKeepInMemory;
}
/**
* Indicates whether a material file to be loaded has already been set.
*
* @return True if material file has already been provided, false otherwise.
*/
public boolean hasFile() {
return reader != null;
}
/**
* Sets material file to be loaded.
*
* @param f material file to be loaded.
* @throws LockedException raised if this instance is loaded because a file
* is already being loaded.
* @throws IOException raised if provided file does not exist or if an I/O
* exception occurs.
*/
@SuppressWarnings("DuplicatedCode")
public void setFile(final File f) throws LockedException, IOException {
if (isLocked()) {
throw new LockedException();
}
file = f;
if (reader != null) {
// close previous file
reader.close();
}
if (f.length() < fileSizeLimitToKeepInMemory) {
reader = new MappedFileReaderAndWriter(f, FileChannel.MapMode.READ_ONLY);
} else {
reader = new FileReaderAndWriter(f, FileChannel.MapMode.READ_ONLY);
}
}
/**
* Closes file provided to this loader.
*
* @throws IOException if an I/O error occurs.
*/
@Override
public void close() throws IOException {
if (reader != null) {
reader.close();
reader = null;
}
}
/**
* Indicates if textures must be validated to ensure that image files are
* valid files.
*
* @return true if textures must be validated, false otherwise.
*/
public boolean isTextureValidationEnabled() {
return textureValidationEnabled;
}
/**
* Specifies whether textures must be validated to ensure that image files
* are valid files.
*
* @param textureValidationEnabled true if textures must be validated, false
* otherwise.
*/
public void setTextureValidationEnabled(final boolean textureValidationEnabled) {
this.textureValidationEnabled = textureValidationEnabled;
}
/**
* Determines whether this instance is locked.
* A material loader remains locked while decoding of a file is being done.
* This instance will remain locked once the loading process starts until
* it finishes either successfully or not.
* While this instance remains locked no parameters can be changed,
* otherwise a LockedException will be raised.
*
* @return True if instance is locked, false otherwise.
*/
public synchronized boolean isLocked() {
return locked;
}
/**
* Sets the lock value of this instance so that no parameters cannot be
* changed until this instance is unlocked.
*
* @param locked value that determines whether this instance is locked or
* not.
*/
protected synchronized void setLocked(final boolean locked) {
this.locked = locked;
}
/**
* Returns material listener of this instance.
* A material listener notifies of start, end and progress change events.
*
* @return material listener of this instance.
*/
public MaterialLoaderListener getListener() {
return listener;
}
/**
* Sets material listener of this instance.
* A material listener notifies of start, end and progress change events.
*
* @param listener material listener of this instance.
* @throws LockedException Raised if this instance is already locked.
*/
public void setListener(final MaterialLoaderListener listener) throws LockedException {
if (isLocked()) {
throw new LockedException();
}
this.listener = listener;
}
/**
* Determines whether enough parameters have been set so that the loading
* process can start.
*
* @return True if this instance is ready to start loading a file, false
* otherwise.
*/
public abstract boolean isReady();
/**
* Starts the loading process of provided file.
* This method returns a set containing all the materials that have been
* loaded.
*
* @return a set containing all the materials that have been loaded.
* @throws LockedException raised if this instance is already locked.
* @throws NotReadyException raised if this instance is not yet ready.
* @throws IOException if an I/O error occurs.
* @throws LoaderException if file is corrupted or cannot be interpreted.
*/
public abstract Set<Material> load() throws LockedException, NotReadyException, IOException, LoaderException;
}