Checkpoint commit. Added AttachmentFactory interface and
BaseAttachmentFactory. Reimplemented DecalRegistry to implement AttachmentFactory and contain a delegate BaseAttachmentFactory.
This commit is contained in:
parent
05ff94836f
commit
8ad89448df
@ -0,0 +1,7 @@
|
||||
package net.sf.openrocket.document;
|
||||
|
||||
public interface AttachmentFactory<T extends Attachment> {
|
||||
|
||||
public T getAttachment(String name);
|
||||
|
||||
}
|
135
core/src/net/sf/openrocket/document/BaseAttachmentFactory.java
Normal file
135
core/src/net/sf/openrocket/document/BaseAttachmentFactory.java
Normal file
@ -0,0 +1,135 @@
|
||||
package net.sf.openrocket.document;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.sf.openrocket.file.FileInfo;
|
||||
import net.sf.openrocket.util.FileUtils;
|
||||
|
||||
public class BaseAttachmentFactory implements AttachmentFactory<BaseAttachmentFactory.BaseAttachment> {
|
||||
|
||||
private FileInfo fileInfo;
|
||||
private boolean isZipFile = false;
|
||||
|
||||
public void setBaseFile(FileInfo fileInfo) {
|
||||
this.fileInfo = fileInfo;
|
||||
}
|
||||
|
||||
public void setIsZipFile(boolean isZipFile) {
|
||||
this.isZipFile = isZipFile;
|
||||
}
|
||||
|
||||
public class BaseAttachment implements Attachment, Comparable {
|
||||
|
||||
protected String name;
|
||||
|
||||
BaseAttachment(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBytes() throws FileNotFoundException, IOException {
|
||||
return BaseAttachmentFactory.this.getBytes(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
if (!(o instanceof BaseAttachment)) {
|
||||
return -1;
|
||||
}
|
||||
return this.name.compareTo(((BaseAttachment) o).name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseAttachment getAttachment(String name) {
|
||||
return new BaseAttachment(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns an InputStream backed by a byte[] containing the decal pixels.
|
||||
* If it reads in the bytes from an actual file, the underlying file is closed.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
private InputStream getBytes(BaseAttachment attachment) throws FileNotFoundException, IOException {
|
||||
|
||||
// This is the InputStream to be returned.
|
||||
InputStream rawIs = null;
|
||||
|
||||
|
||||
String name = attachment.getName();
|
||||
|
||||
if (rawIs == null && isZipFile) {
|
||||
rawIs = findInZipContainer(name);
|
||||
}
|
||||
|
||||
// Try relative to the model file directory. This is so we can support unzipped container format.
|
||||
if (rawIs == null) {
|
||||
if (fileInfo != null && fileInfo.getDirectory() != null) {
|
||||
File decalFile = new File(fileInfo.getDirectory(), name);
|
||||
rawIs = new FileInputStream(decalFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (rawIs == null) {
|
||||
throw new FileNotFoundException("Unable to locate decal for name " + name);
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] bytes = FileUtils.readBytes(rawIs);
|
||||
return new ByteArrayInputStream(bytes);
|
||||
} finally {
|
||||
rawIs.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ZipInputStream findInZipContainer(String name) {
|
||||
ZipInputStream zis = null;
|
||||
try {
|
||||
zis = new ZipInputStream(fileInfo.getFileURL().openStream());
|
||||
} catch (IOException ex) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
ZipEntry entry = zis.getNextEntry();
|
||||
while (entry != null) {
|
||||
if (entry.getName().equals(name)) {
|
||||
return zis;
|
||||
}
|
||||
entry = zis.getNextEntry();
|
||||
}
|
||||
zis.close();
|
||||
return null;
|
||||
} catch (IOException ioex) {
|
||||
try {
|
||||
zis.close();
|
||||
} catch (IOException ex) {
|
||||
// why does close throw? it's maddening
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -10,49 +10,43 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.sf.openrocket.appearance.DecalImage;
|
||||
import net.sf.openrocket.file.FileInfo;
|
||||
import net.sf.openrocket.document.BaseAttachmentFactory.BaseAttachment;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
import net.sf.openrocket.util.FileUtils;
|
||||
|
||||
public class DecalRegistry {
|
||||
public class DecalRegistry implements AttachmentFactory<DecalImage> {
|
||||
private static LogHelper log = Application.getLogger();
|
||||
|
||||
private FileInfo fileInfo;
|
||||
private boolean isZipFile = false;
|
||||
private final BaseAttachmentFactory baseFactory;
|
||||
|
||||
public DecalRegistry(BaseAttachmentFactory baseFactory) {
|
||||
this.baseFactory = baseFactory;
|
||||
}
|
||||
|
||||
private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>();
|
||||
|
||||
public void setBaseFile(FileInfo fileInfo) {
|
||||
this.fileInfo = fileInfo;
|
||||
}
|
||||
|
||||
public void setIsZipFile( boolean isZipFile ) {
|
||||
this.isZipFile = isZipFile;
|
||||
}
|
||||
|
||||
public DecalImage getDecalImage( String decalName ) {
|
||||
public DecalImage getAttachment(String decalName) {
|
||||
DecalImageImpl d = registeredDecals.get(decalName);
|
||||
if (d == null) {
|
||||
d = new DecalImageImpl(decalName);
|
||||
BaseAttachment attachment = baseFactory.getAttachment(decalName);
|
||||
d = new DecalImageImpl(attachment);
|
||||
registeredDecals.put(decalName, d);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
public DecalImage getDecalImage( File file ) {
|
||||
public DecalImage getAttachment(File file) {
|
||||
|
||||
// See if this file is being used already
|
||||
DecalImageImpl decal = findDecalForFile(file);
|
||||
@ -64,7 +58,8 @@ public class DecalRegistry {
|
||||
// It's a new file, generate a name for it.
|
||||
String decalName = makeUniqueName(file.getName());
|
||||
|
||||
decal = new DecalImageImpl( decalName );
|
||||
BaseAttachment attachment = baseFactory.getAttachment(decalName);
|
||||
decal = new DecalImageImpl(attachment);
|
||||
decal.setFileSystemLocation(file);
|
||||
|
||||
registeredDecals.put(decalName, decal);
|
||||
@ -72,7 +67,7 @@ public class DecalRegistry {
|
||||
|
||||
}
|
||||
|
||||
public Set<DecalImage> getDecalList( ) {
|
||||
public Collection<DecalImage> getDecalList() {
|
||||
|
||||
Set<DecalImage> decals = new TreeSet<DecalImage>();
|
||||
|
||||
@ -81,33 +76,19 @@ public class DecalRegistry {
|
||||
return decals;
|
||||
}
|
||||
|
||||
public Set<DecalImage> getExportableDecalsList() {
|
||||
|
||||
Set<DecalImage> exportableDecals = new HashSet<DecalImage>();
|
||||
|
||||
for( DecalImage d : registeredDecals.values() ) {
|
||||
if ( isExportable(d.getName())) {
|
||||
exportableDecals.add(d);
|
||||
}
|
||||
}
|
||||
|
||||
return exportableDecals;
|
||||
|
||||
}
|
||||
|
||||
public class DecalImageImpl implements DecalImage, Comparable {
|
||||
|
||||
private final String name;
|
||||
private final BaseAttachment delegate;
|
||||
|
||||
private File fileSystemLocation;
|
||||
|
||||
private DecalImageImpl( String name ) {
|
||||
this.name = name;
|
||||
private DecalImageImpl(BaseAttachment delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
return delegate.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -117,8 +98,8 @@ public class DecalRegistry {
|
||||
|
||||
@Override
|
||||
public void exportImage(File file, boolean watchForChanges) throws IOException {
|
||||
this.fileSystemLocation = file;
|
||||
DecalRegistry.this.exportDecal(this, file);
|
||||
this.fileSystemLocation = file;
|
||||
}
|
||||
|
||||
File getFileSystemLocation() {
|
||||
@ -131,7 +112,7 @@ public class DecalRegistry {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,35 +120,11 @@ public class DecalRegistry {
|
||||
if (!(o instanceof DecalImageImpl)) {
|
||||
return -1;
|
||||
}
|
||||
return this.name.compareTo( ((DecalImageImpl)o).name );
|
||||
return delegate.compareTo(((DecalImageImpl) o).delegate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the named decal is exportable - that is, it is currently stored in
|
||||
* the zip file.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
private boolean isExportable( String name ) {
|
||||
if ( !isZipFile ) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
InputStream is = findInZipContainer(name);
|
||||
if ( is != null ) {
|
||||
is.close();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch ( IOException iex ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns an InputStream backed by a byte[] containing the decal pixels.
|
||||
* If it reads in the bytes from an actual file, the underlying file is closed.
|
||||
@ -179,44 +136,23 @@ public class DecalRegistry {
|
||||
*/
|
||||
private InputStream getDecal(DecalImageImpl decal) throws FileNotFoundException, IOException {
|
||||
|
||||
// This is the InputStream to be returned.
|
||||
InputStream rawIs = null;
|
||||
|
||||
|
||||
// First check if the decal is located on the file system
|
||||
File exportedFile = decal.getFileSystemLocation();
|
||||
if (exportedFile != null) {
|
||||
rawIs = new FileInputStream(exportedFile);
|
||||
}
|
||||
|
||||
String name = decal.getName();
|
||||
|
||||
if ( rawIs == null && isZipFile ) {
|
||||
rawIs = findInZipContainer(name);
|
||||
}
|
||||
|
||||
// Try relative to the model file directory. This is so we can support unzipped container format.
|
||||
if ( rawIs == null ) {
|
||||
if( fileInfo != null && fileInfo.getDirectory() != null ) {
|
||||
File decalFile = new File(fileInfo.getDirectory(), name);
|
||||
rawIs = new FileInputStream(decalFile);
|
||||
}
|
||||
}
|
||||
|
||||
if ( rawIs == null ) {
|
||||
throw new FileNotFoundException( "Unable to locate decal for name " + name );
|
||||
}
|
||||
|
||||
InputStream rawIs = new FileInputStream(exportedFile);
|
||||
try {
|
||||
byte[] bytes = FileUtils.readBytes(rawIs);
|
||||
return new ByteArrayInputStream(bytes);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
rawIs.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return decal.delegate.getBytes();
|
||||
|
||||
}
|
||||
|
||||
private void exportDecal(DecalImageImpl decal, File selectedFile) throws IOException {
|
||||
|
||||
try {
|
||||
@ -228,42 +164,12 @@ public class DecalRegistry {
|
||||
is.close();
|
||||
os.close();
|
||||
|
||||
}
|
||||
catch (IOException iex) {
|
||||
} catch (IOException iex) {
|
||||
throw new BugException(iex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private ZipInputStream findInZipContainer( String name ) {
|
||||
ZipInputStream zis = null;
|
||||
try {
|
||||
zis = new ZipInputStream(fileInfo.fileURL.openStream());
|
||||
} catch( IOException ex ) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
ZipEntry entry = zis.getNextEntry();
|
||||
while ( entry != null ) {
|
||||
if ( entry.getName().equals(name) ) {
|
||||
return zis;
|
||||
}
|
||||
entry = zis.getNextEntry();
|
||||
}
|
||||
zis.close();
|
||||
return null;
|
||||
}
|
||||
catch ( IOException ioex ) {
|
||||
try {
|
||||
zis.close();
|
||||
} catch ( IOException ex ) {
|
||||
// why does close throw? it's maddening
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private DecalImageImpl findDecalForFile(File file) {
|
||||
|
||||
for (DecalImageImpl d : registeredDecals.values()) {
|
||||
|
@ -6,20 +6,17 @@ import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.sf.openrocket.appearance.Appearance;
|
||||
import net.sf.openrocket.appearance.Decal;
|
||||
import net.sf.openrocket.document.events.DocumentChangeEvent;
|
||||
import net.sf.openrocket.document.events.DocumentChangeListener;
|
||||
import net.sf.openrocket.document.events.SimulationChangeEvent;
|
||||
import net.sf.openrocket.file.FileInfo;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.logging.TraceException;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
|
||||
import net.sf.openrocket.rocketcomponent.Configuration;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.simulation.FlightDataType;
|
||||
import net.sf.openrocket.simulation.customexpression.CustomExpression;
|
||||
import net.sf.openrocket.simulation.listeners.SimulationListener;
|
||||
@ -62,7 +59,8 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
||||
private final ArrayList<Simulation> simulations = new ArrayList<Simulation>();
|
||||
private ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
|
||||
|
||||
private DecalRegistry decalRegistry = new DecalRegistry();
|
||||
private BaseAttachmentFactory attachmentFactory = new BaseAttachmentFactory();
|
||||
private DecalRegistry decalRegistry = new DecalRegistry(attachmentFactory);
|
||||
|
||||
/*
|
||||
* The undo/redo variables and mechanism are documented in doc/undo-redo-flow.*
|
||||
@ -115,6 +113,16 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
||||
}
|
||||
|
||||
|
||||
public void setBaseFile(FileInfo fileInfo) {
|
||||
attachmentFactory.setBaseFile(fileInfo);
|
||||
}
|
||||
|
||||
|
||||
public void setIsZipFile(boolean isZipFile) {
|
||||
attachmentFactory.setIsZipFile(isZipFile);
|
||||
}
|
||||
|
||||
|
||||
public void addCustomExpression(CustomExpression expression) {
|
||||
if (customExpressions.contains(expression)) {
|
||||
log.user("Could not add custom expression " + expression.getName() + " to document as document alerady has a matching expression.");
|
||||
|
@ -69,7 +69,7 @@ public class GeneralRocketLoader {
|
||||
public final OpenRocketDocument load(InputStream source, FileInfo fileInfo, MotorFinder motorFinder) throws RocketLoadException {
|
||||
try {
|
||||
OpenRocketDocument doc = loadFromStream(source, motorFinder);
|
||||
doc.getDecalRegistry().setBaseFile(fileInfo);
|
||||
doc.setBaseFile(fileInfo);
|
||||
return doc;
|
||||
} catch (Exception e) {
|
||||
throw new RocketLoadException("Exception loading stream", e);
|
||||
@ -105,7 +105,7 @@ public class GeneralRocketLoader {
|
||||
// Check for GZIP
|
||||
if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
|
||||
OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source), motorFinder);
|
||||
doc.getDecalRegistry().setIsZipFile(false);
|
||||
doc.setIsZipFile(false);
|
||||
return doc;
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ public class GeneralRocketLoader {
|
||||
}
|
||||
if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
|
||||
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
||||
doc.getDecalRegistry().setIsZipFile(true);
|
||||
doc.setIsZipFile(true);
|
||||
return doc;
|
||||
} else if (entry.getName().matches(".*\\.[rR][kK][tT]$")) {
|
||||
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
||||
@ -136,7 +136,7 @@ public class GeneralRocketLoader {
|
||||
match++;
|
||||
if (match == OPENROCKET_SIGNATURE.length) {
|
||||
OpenRocketDocument doc = loadUsing(openRocketLoader, source, motorFinder);
|
||||
doc.getDecalRegistry().setIsZipFile(false);
|
||||
doc.setIsZipFile(false);
|
||||
return doc;
|
||||
}
|
||||
} else {
|
||||
@ -147,7 +147,7 @@ public class GeneralRocketLoader {
|
||||
byte[] typeIdentifier = ArrayUtils.copyOf(buffer, ROCKSIM_SIGNATURE.length);
|
||||
if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
|
||||
OpenRocketDocument doc = loadUsing(rocksimLoader, source, motorFinder);
|
||||
doc.getDecalRegistry().setIsZipFile(false);
|
||||
doc.setIsZipFile(false);
|
||||
return doc;
|
||||
}
|
||||
throw new RocketLoadException("Unsupported or corrupt file.");
|
||||
|
@ -31,7 +31,7 @@ class AppearanceHandler extends AbstractElementHandler {
|
||||
throws SAXException {
|
||||
if ("decal".equals(element)) {
|
||||
String name = attributes.remove("name");
|
||||
builder.setImage(context.getOpenRocketDocument().getDecalRegistry().getDecalImage(name));
|
||||
builder.setImage(context.getOpenRocketDocument().getDecalRegistry().getAttachment(name));
|
||||
double rotation = Double.parseDouble(attributes.remove("rotation"));
|
||||
builder.setRotation(rotation);
|
||||
String edgeModeName = attributes.remove("edgemode");
|
||||
|
@ -68,7 +68,7 @@ public class RockSimAppearanceBuilder extends AppearanceBuilder {
|
||||
//Find out how to get path of current rocksim file
|
||||
//so I can look in it's directory
|
||||
}
|
||||
setImage(document.getDecalRegistry().getDecalImage(value));
|
||||
setImage(document.getDecalRegistry().getAttachment(value));
|
||||
}
|
||||
} else if ("repeat".equals(name)) {
|
||||
repeat = "1".equals(value);
|
||||
|
@ -5,7 +5,7 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
@ -40,7 +40,7 @@ public class ExportDecalDialog extends JDialog {
|
||||
JLabel label = new JLabel(trans.get("ExportDecalDialog.decalList.lbl"));
|
||||
panel.add(label);
|
||||
|
||||
Set<DecalImage> exportableDecals = document.getDecalRegistry().getExportableDecalsList();
|
||||
Collection<DecalImage> exportableDecals = document.getDecalRegistry().getDecalList();
|
||||
|
||||
decalComboBox = new JComboBox(exportableDecals.toArray(new DecalImage[0]));
|
||||
decalComboBox.setEditable(false);
|
||||
@ -79,8 +79,7 @@ public class ExportDecalDialog extends JDialog {
|
||||
|
||||
try {
|
||||
decal.exportImage(selectedFile, false);
|
||||
}
|
||||
catch (IOException iex) {
|
||||
} catch (IOException iex) {
|
||||
throw new BugException(iex);
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class DecalModel extends AbstractListModel implements ComboBoxModel {
|
||||
if (action == JFileChooser.APPROVE_OPTION) {
|
||||
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(fc.getCurrentDirectory());
|
||||
File file = fc.getSelectedFile();
|
||||
setSelectedItem(document.getDecalRegistry().getDecalImage(file));
|
||||
setSelectedItem(document.getDecalRegistry().getAttachment(file));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user