/*
* Copyright (C) 2010 Medo <smaxein@googlemail.com>
*
* This file is part of GmkSplitter.
* GmkSplitter is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package com.ganggarrison.gmdec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.lateralgm.components.impl.ResNode;
import org.lateralgm.file.GmFile;
import org.lateralgm.file.GmFile.FormatFlavor;
import org.lateralgm.file.GmFileReader;
import org.lateralgm.file.GmFileWriter;
import org.lateralgm.file.GmFormatException;
import org.lateralgm.resources.library.LibManager;
import org.lateralgm.resources.sub.Constant;
import com.ganggarrison.easyxml.XmlReader;
import com.ganggarrison.gmdec.files.IncludedFileFormat;
import com.ganggarrison.gmdec.xml.ConstantsXmlFormat;
public class GmkSplitter {
private static final String CONSTANTS_FILENAME = "Constants.xml";
public enum IdPreservation {
NONE, OBJECTS, ALL
};
public static boolean convertLineEndings = true;
public static boolean omitDisabledFields = true;
public static IdPreservation preserveIds = IdPreservation.OBJECTS;
public static int targetVersion = 800;
public static void main(String[] args) throws IOException {
if (args.length != 2) {
printUsage();
return;
}
if (isGmkFile(args[0])) {
File gmkFile = new File(args[0]);
File dir = new File(args[1]);
if (!gmkFile.isFile()) {
System.err.println("Source file " + gmkFile + " not found.");
return;
}
if (dir.exists()) {
System.err.println("Destination directory " + dir + " already exists.");
return;
}
decompose(gmkFile, dir);
} else if (isGmkFile(args[1])) {
File dir = new File(args[0]);
File gmkFile = new File(args[1]);
if (!dir.isDirectory()) {
System.err.println("Source directory " + dir + " not found.");
return;
}
if (gmkFile.exists()) {
System.err.println("Destination file " + gmkFile + " already exists.");
return;
}
compose(dir, gmkFile);
} else {
printUsage();
}
}
private static void printUsage() {
System.out.println("Usage: java -jar GmkSplit.jar <source> <dest>");
System.out.println("One of <source> or <dest> must be the name of a .gmk or .gm81 file.");
System.out.println("Using a .gmk file as destination will create a GM 8.0 file.");
System.out.println("Using a .gm81 file as destination will create a GM 8.1 file.");
System.out.println("The destination must not already exist. This tool won't overwrite.");
}
private static boolean isGmkFile(String arg) {
return arg.toLowerCase().endsWith(".gmk") || arg.toLowerCase().endsWith(".gm81");
}
public static void decompose(File sourceGmk, File destinationPath) throws IOException {
LibManager.autoLoad();
try {
ResNode root = new ResNode("Root", (byte) 0, null, null);
FileInputStream fis = new FileInputStream(sourceGmk);
GmFile gmf;
try {
gmf = GmFileReader.readGmFile(fis, sourceGmk.toURI(), root);
} finally {
try {
fis.close();
} catch (IOException e) {
}
}
if (gmf.format != FormatFlavor.GM_800 && gmf.format != FormatFlavor.GM_810) {
System.err
.println("Warning: The source file is not of GM version 8 or 8.1. GMK Splitter is *not tested* with this format.");
}
targetVersion = gmf.format.getVersion();
ResourceWriter.writeTree(root, gmf, destinationPath);
writeConstants(gmf, destinationPath);
writeIncludedFiles(gmf, destinationPath);
} catch (GmFormatException e) {
throw new IOException(e);
}
}
public static void compose(File sourcePath, File destinationGmk) throws IOException {
LibManager.autoLoad();
GmFile gmf = new GmFile();
gmf.uri = destinationGmk.toURI();
targetVersion = destinationGmk.getName().toLowerCase().endsWith(".gmk") ? 800 : 810;
ResNode root = new ResNode("Root", (byte) 0, null, null);
new ResourceReader().readTree(root, gmf, sourcePath);
readConstants(gmf, sourcePath);
readIncludedFiles(gmf, sourcePath);
FileOutputStream fos = new FileOutputStream(destinationGmk);
try {
GmFileWriter.writeGmFile(fos, gmf, root, targetVersion);
} finally {
fos.close();
}
}
private static void writeConstants(GmFile gmf, File destinationPath) throws IOException {
File constantsFile = new File(destinationPath, CONSTANTS_FILENAME);
new ConstantsXmlFormat().write(gmf.constants, constantsFile);
}
private static void readConstants(GmFile gmf, File sourcePath) throws IOException {
File constantsFile = new File(sourcePath, CONSTANTS_FILENAME);
List<Constant> constants = new ConstantsXmlFormat().read(new XmlReader(constantsFile));
gmf.constants = new ArrayList<Constant>(constants);
}
private static String INCLUDED_FILES_DIR = "Included Files";
private static void writeIncludedFiles(GmFile gmf, File destinationPath) throws IOException {
if (!gmf.includes.isEmpty()) {
File includedFilesPath = new File(destinationPath, INCLUDED_FILES_DIR);
if (!includedFilesPath.mkdirs()) {
throw new IOException("Unable to create path: " + includedFilesPath);
}
IncludedFileFormat.write(includedFilesPath, gmf.includes);
}
}
private static void readIncludedFiles(GmFile gmf, File sourcePath) throws IOException {
File includedFilesPath = new File(sourcePath, INCLUDED_FILES_DIR);
if (includedFilesPath.isDirectory()) {
IncludedFileFormat.read(includedFilesPath, gmf);
}
}
private static HashSet<String> issuedVersionWarnings = new HashSet<String>();
public static void issueVersionWarning(String info) {
if (!issuedVersionWarnings.contains(info)) {
System.err.println("Warning: The information \"" + info
+ "\" cannot be represented in the target format.");
issuedVersionWarnings.add(info);
}
}
}