Commit 1cf6605c authored by Riegel's avatar Riegel
Browse files

Docs: Add Javadoc

2 merge requests!28Version 3.17.0 Release,!26Add ZIP-archive support
Pipeline #10989 passed with stage
in 1 minute and 27 seconds
This commit is part of merge request !26. Comments created here will be created in the context of that merge request.
Showing with 136 additions and 20 deletions
+136 -20
...@@ -18,6 +18,10 @@ import java.util.zip.ZipEntry; ...@@ -18,6 +18,10 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
/**
* This class serves as a representation of a ZIP-archive containing CityGml files. The contained files are represented
* by {@link CityGmlZipEntry} objects.
*/
public class CityGmlZipArchive implements Serializable { public class CityGmlZipArchive implements Serializable {
private static final Logger logger = LogManager.getLogger(CityGmlZipArchive.class); private static final Logger logger = LogManager.getLogger(CityGmlZipArchive.class);
...@@ -29,7 +33,13 @@ public class CityGmlZipArchive implements Serializable { ...@@ -29,7 +33,13 @@ public class CityGmlZipArchive implements Serializable {
private final Path archivePath; private final Path archivePath;
private final String archiveNameRE; private final String archiveNameRE;
/**
* Registers a ZIP-file as an archive. All contained XML and GML files will be registered as {@link CityGmlZipEntry} objects.
*
* @param zipFile path of the ZIP-file
* @return A {@link CityGmlZipArchive} object representing the archive, or null if read-access for the ZIP-file was denied
* @throws MalformedZipFileException if the ZIP-file has encoding errors
*/
public static CityGmlZipArchive register(String zipFile) throws MalformedZipFileException { public static CityGmlZipArchive register(String zipFile) throws MalformedZipFileException {
ArrayList<CityGmlZipEntry> archiveEntries = new ArrayList<>(); ArrayList<CityGmlZipEntry> archiveEntries = new ArrayList<>();
CityGmlZipArchive cgmlArchive = new CityGmlZipArchive(Path.of(zipFile)); CityGmlZipArchive cgmlArchive = new CityGmlZipArchive(Path.of(zipFile));
...@@ -40,6 +50,7 @@ public class CityGmlZipArchive implements Serializable { ...@@ -40,6 +50,7 @@ public class CityGmlZipArchive implements Serializable {
continue; continue;
} }
if (ze.getName().endsWith(".gml") || ze.getName().endsWith(".xml")) { if (ze.getName().endsWith(".gml") || ze.getName().endsWith(".xml")) {
// Ignore report files generated by CityDoctor
if (ze.getName().endsWith("_report.xml")) { if (ze.getName().endsWith("_report.xml")) {
continue; continue;
} }
...@@ -62,6 +73,11 @@ public class CityGmlZipArchive implements Serializable { ...@@ -62,6 +73,11 @@ public class CityGmlZipArchive implements Serializable {
} }
} }
/**
* Attempts to load all contained {@link CityGmlZipEntry} objects into memory.
*
* @param config Parser configuration for the entries
*/
public void mountArchive(ParserConfiguration config) { public void mountArchive(ParserConfiguration config) {
try (ZipFile zip = new ZipFile(archivePath.toFile())) { try (ZipFile zip = new ZipFile(archivePath.toFile())) {
for (CityGmlZipEntry entry : entries) { for (CityGmlZipEntry entry : entries) {
...@@ -79,34 +95,55 @@ public class CityGmlZipArchive implements Serializable { ...@@ -79,34 +95,55 @@ public class CityGmlZipArchive implements Serializable {
private void setEntries(List<CityGmlZipEntry> entries) { private void setEntries(List<CityGmlZipEntry> entries) {
this.entries = entries; this.entries = entries;
entries.forEach(e -> e.setArchive(this));
} }
/**
* Saves this archive as a ZIP-file.
* @param path target path for the export
*/
public void exportToZipFile(String path) { public void exportToZipFile(String path) {
ArchivePacker.packArchive(path, this); ArchivePacker.packArchive(path, this);
} }
/**
public CityGmlZipEntry getEntry(String fileName) { * Gets an entry in this archive by its subpath.
fileName = stripArchivePath(fileName); *
* @param subpath subpath to the entry from this archive's root directory
* @return the corresponding entry, or null if entry could not be found
*/
public CityGmlZipEntry getEntry(String subpath) {
subpath = stripArchivePath(subpath);
for (CityGmlZipEntry entry : entries) { for (CityGmlZipEntry entry : entries) {
String entryName = stripArchivePath(entry.getEntrySubPath()); String entryName = stripArchivePath(entry.getEntrySubPath());
if (entryName.equals(fileName)) { if (entryName.equals(subpath)) {
return entry; return entry;
} }
} }
return null; return null;
} }
/**
* Strips the root directory name of this archive from an entry subpath.
* @param path the relative path to the entry
* @return String of the path without the root directory
*/
private String stripArchivePath(String path) { private String stripArchivePath(String path) {
Path systemPath = Path.of(path); Path systemPath = Path.of(path);
return systemPath.toString().replace(archiveNameRE, ""); return systemPath.toString().replace(archiveNameRE, "");
} }
/**
* Gets the path to the ZIP-file associated with this archive.
* @return path of the ZIP-file
*/
public Path getArchivePath() { public Path getArchivePath() {
return archivePath; return archivePath;
} }
/**
* Gets the entry list of this archive.
* @return the entry list
*/
public List<CityGmlZipEntry> getEntries() { public List<CityGmlZipEntry> getEntries() {
return entries; return entries;
} }
......
...@@ -15,6 +15,11 @@ import java.io.Serializable; ...@@ -15,6 +15,11 @@ import java.io.Serializable;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
/**
* This class serves as a representation of a CityGml file in a ZIP archive.
* <p/>
* The {@link CityDoctorModel} of the associated file can only be accessed after loading the corresponding entry.
*/
public class CityGmlZipEntry implements Serializable { public class CityGmlZipEntry implements Serializable {
private static final Logger logger = LogManager.getLogger(CityGmlZipEntry.class); private static final Logger logger = LogManager.getLogger(CityGmlZipEntry.class);
...@@ -31,16 +36,28 @@ public class CityGmlZipEntry implements Serializable { ...@@ -31,16 +36,28 @@ public class CityGmlZipEntry implements Serializable {
private static final long MB = 1024 * 1024L; private static final long MB = 1024 * 1024L;
private ZipEntryErrorType errorType = null; private ZipEntryErrorType errorType = null;
public static CityGmlZipEntry of(ZipEntry entry, CityGmlZipArchive parentArchive, ParserConfiguration config) {
CityGmlZipEntry ze = CityGmlZipEntry.register(entry, parentArchive);
ze.loadEntry(config);
return ze;
}
/**
* Attempts to parse the CityGML model associated with this entry and loads it into memory.
* <p/>
* In the event of a parsing error, the entry will be flagged by assigning the appropriate
* {@link ZipEntryErrorType} to the errorType field.
*
* @param config Parser configuration for this model
*/
public void loadEntry(ParserConfiguration config) { public void loadEntry(ParserConfiguration config) {
loadEntry(config, null); loadEntry(config, null);
} }
/**
* Attempts to parse the CityGML model associated with this entry and loads it into memory.
* <p/>
* In the event of a parsing error, the entry will be flagged by assigning the appropriate
* {@link ZipEntryErrorType} to the errorType field.
*
* @param config Parser configuration for this model
* @param l ProgressListener for tracking parsing progress
*/
public void loadEntry(ParserConfiguration config, ProgressListener l) { public void loadEntry(ParserConfiguration config, ProgressListener l) {
if (inMemory) { if (inMemory) {
return; return;
...@@ -61,6 +78,16 @@ public class CityGmlZipEntry implements Serializable { ...@@ -61,6 +78,16 @@ public class CityGmlZipEntry implements Serializable {
} }
} }
/**
* Registers a {@link ZipEntry ZipEntry} in a ZIP-archive as a {@link CityGmlZipEntry}.
* <p/>
* If the filesize of the associated file exceeds the total available system memory, or read access is denied,
* the entry will be flagged by assigning the appropriate {@link ZipEntryErrorType} to the errorType field.
*
* @param entry The ZipEntry object
* @param parentArchive The parent archive for this entry
* @return A corresponding CityGmlZipEntry object
*/
public static CityGmlZipEntry register(ZipEntry entry, CityGmlZipArchive parentArchive) { public static CityGmlZipEntry register(ZipEntry entry, CityGmlZipArchive parentArchive) {
CityGmlZipEntry cgzEntry = new CityGmlZipEntry(entry, parentArchive, false); CityGmlZipEntry cgzEntry = new CityGmlZipEntry(entry, parentArchive, false);
try { try {
...@@ -74,6 +101,12 @@ public class CityGmlZipEntry implements Serializable { ...@@ -74,6 +101,12 @@ public class CityGmlZipEntry implements Serializable {
return cgzEntry; return cgzEntry;
} }
/**
* Checks if the filesize of this entry would exceed the system's available memory.
*
* @return true if within limits, false otherwise
* @throws IOException if read access to the ZIP-archive is denied
*/
private boolean entrySizeWithinMemoryLimits() throws IOException { private boolean entrySizeWithinMemoryLimits() throws IOException {
long memoryLimit = (long) Math.ceil(((double) Runtime.getRuntime().maxMemory() / MB) * 0.9); long memoryLimit = (long) Math.ceil(((double) Runtime.getRuntime().maxMemory() / MB) * 0.9);
if (fileSize == -1L) { if (fileSize == -1L) {
...@@ -103,31 +136,43 @@ public class CityGmlZipEntry implements Serializable { ...@@ -103,31 +136,43 @@ public class CityGmlZipEntry implements Serializable {
this.parentArchive = parentArchive; this.parentArchive = parentArchive;
} }
public void setArchive(CityGmlZipArchive archive) { /**
parentArchive = archive; * Gets the parent archive of this entry.
} * @return the archive
*/
public CityGmlZipArchive getArchive() { public CityGmlZipArchive getArchive() {
return parentArchive; return parentArchive;
} }
/** /**
* Gets this entry's sub-path in the archive. * Gets the sub-path in the archive of the file associated with this entry.
* *
* @return Relative sub-path from the archive root directory. * @return the relative sub-path from the archive root directory
*/ */
public String getEntrySubPath() { public String getEntrySubPath() {
return fileName; return fileName;
} }
/**
* Gets the name of the file associated with this entry.
* @return the filename
*/
public String getDisplayName() { public String getDisplayName() {
return displayName; return displayName;
} }
/**
* Gets the {@link ZipEntryErrorType} of this entry.
* @return the error type, or null if this entry is not erroneous
*/
public ZipEntryErrorType getErrorType() { public ZipEntryErrorType getErrorType() {
return errorType; return errorType;
} }
/**
* Gets the {@link CityDoctorModel} of this entry.
* @return The model, or null if the entry has not been loaded or is erroneous
*/
public CityDoctorModel getModel() { public CityDoctorModel getModel() {
return model; return model;
} }
...@@ -136,14 +181,20 @@ public class CityGmlZipEntry implements Serializable { ...@@ -136,14 +181,20 @@ public class CityGmlZipEntry implements Serializable {
fileSize = size; fileSize = size;
} }
/**
* Resolves the reference path of a {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject LibraryObject}
* in the {@link CityDoctorModel} of this entry.
* @param libraryObjectPath The reference path to the LibraryObject's CityGml file
* @return Relative sub-path within the archive to the CityGml file
*/
public Path resolveLibraryObjectPath(String libraryObjectPath) { public Path resolveLibraryObjectPath(String libraryObjectPath) {
return filePath.getParent().resolve(libraryObjectPath); return filePath.getParent().resolve(libraryObjectPath);
} }
/** /**
* Returns whether this entry has been loaded into memory. * Checks if the {@link CityDoctorModel} of this entry has been loaded into memory.
* *
* @return true if * @return true if it is loaded, false otherwise
*/ */
public boolean isLoaded() { public boolean isLoaded() {
return inMemory; return inMemory;
...@@ -152,7 +203,7 @@ public class CityGmlZipEntry implements Serializable { ...@@ -152,7 +203,7 @@ public class CityGmlZipEntry implements Serializable {
/** /**
* Returns the estimated uncompressed filesize of this entry. * Returns the estimated uncompressed filesize of this entry.
* *
* @return filesize in bytes, -1 if filesize unknown * @return filesize in bytes, -1L if filesize is unknown
*/ */
public long getFileSize() { public long getFileSize() {
return fileSize; return fileSize;
......
...@@ -6,6 +6,12 @@ import java.io.InputStream; ...@@ -6,6 +6,12 @@ import java.io.InputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
/**
* This class serves as a resource for read-access to the file that is being represented by
* a CityGmlZipEntry object.
* <p/>
* Does not decompress the file or the parent ZIP-archive.
*/
public class CityGmlZipEntryFile implements AutoCloseable { public class CityGmlZipEntryFile implements AutoCloseable {
private final ZipFile zip; private final ZipFile zip;
...@@ -13,6 +19,12 @@ public class CityGmlZipEntryFile implements AutoCloseable { ...@@ -13,6 +19,12 @@ public class CityGmlZipEntryFile implements AutoCloseable {
private final CityGmlZipEntry cgmlZipEntry; private final CityGmlZipEntry cgmlZipEntry;
private boolean closed = false; private boolean closed = false;
/**
* Creates a {@link CityGmlZipEntryFile} for a {@link CityGmlZipEntry} object's referenced file.
*
* @param entry the requested entry
* @throws IOException if read access to the ZIP-archive is denied.
*/
public CityGmlZipEntryFile(CityGmlZipEntry entry) throws IOException { public CityGmlZipEntryFile(CityGmlZipEntry entry) throws IOException {
CityGmlZipArchive archive = entry.getArchive(); CityGmlZipArchive archive = entry.getArchive();
zip = new ZipFile(archive.getArchivePath().toFile()); zip = new ZipFile(archive.getArchivePath().toFile());
...@@ -20,6 +32,14 @@ public class CityGmlZipEntryFile implements AutoCloseable { ...@@ -20,6 +32,14 @@ public class CityGmlZipEntryFile implements AutoCloseable {
this.cgmlZipEntry = entry; this.cgmlZipEntry = entry;
} }
/**
* Gets a new InputStream of this file.
* <p/>
* Returned streams are independent of each other, but will all be closed when the {@link CityGmlZipEntryFile} object
* is closed.
* @return an InputStream of this file.
* @throws IOException when this method is called after the file has been closed.
*/
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
if (closed){ if (closed){
throw new IOException("Stream closed"); throw new IOException("Stream closed");
...@@ -27,6 +47,11 @@ public class CityGmlZipEntryFile implements AutoCloseable { ...@@ -27,6 +47,11 @@ public class CityGmlZipEntryFile implements AutoCloseable {
return zip.getInputStream(zipEntry); return zip.getInputStream(zipEntry);
} }
/**
* Gets an estimation of this file's filesize.
* @return filesize in bytes, -1L if unknown
* @throws IOException when this method is called after the file has been closed.
*/
public long getFileSize() throws IOException { public long getFileSize() throws IOException {
if (closed){ if (closed){
throw new IOException("Stream closed"); throw new IOException("Stream closed");
......
package de.hft.stuttgart.citydoctor2.zip; package de.hft.stuttgart.citydoctor2.zip;
/**
* Error types for {@link CityGmlZipEntry} objects.
*/
public enum ZipEntryErrorType { public enum ZipEntryErrorType {
INVALID_CITY_GML_FILE, EXCESSIVE_FILESIZE, IO_ERROR INVALID_CITY_GML_FILE, EXCESSIVE_FILESIZE, IO_ERROR
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment