Index: /java/ModDepotAccess/.classpath
===================================================================
--- /java/ModDepotAccess/.classpath	(revision 748)
+++ /java/ModDepotAccess/.classpath	(revision 748)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="lib" path="/_ThirdPartyLibs/httpclient/commons-logging-1.1.1.jar"/>
+	<classpathentry kind="lib" path="/_ThirdPartyLibs/httpclient/httpclient-4.2.2.jar"/>
+	<classpathentry kind="lib" path="/_ThirdPartyLibs/httpclient/httpcore-4.2.2.jar"/>
+	<classpathentry kind="lib" path="/_ThirdPartyLibs/JSON-java.jar"/>
+	<classpathentry kind="lib" path="/_ThirdPartyLibs/xstream-1.4.3.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/HTTPFileDownloader"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
Index: /java/ModDepotAccess/.project
===================================================================
--- /java/ModDepotAccess/.project	(revision 748)
+++ /java/ModDepotAccess/.project	(revision 748)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>ModDepotAccess</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: /java/ModDepotAccess/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /java/ModDepotAccess/.settings/org.eclipse.jdt.core.prefs	(revision 748)
+++ /java/ModDepotAccess/.settings/org.eclipse.jdt.core.prefs	(revision 748)
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
Index: /java/ModDepotAccess/src/net/oni2/moddepot/DepotConfig.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/DepotConfig.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/DepotConfig.java	(revision 748)
@@ -0,0 +1,64 @@
+package net.oni2.moddepot;
+
+import java.util.HashSet;
+
+/**
+ * @author Christian Illy
+ */
+public class DepotConfig {
+	/**
+	 * Node type for package nodes
+	 */
+	public static String nodeType_Package = "mod";
+	/**
+	 * Vocabulary name for the platform terms
+	 */
+	public static String vocabName_Platform = "Platform";
+	/**
+	 * Vocabulary name for the install type terms
+	 */
+	public static String vocabName_InstallType = "Install method";
+	/**
+	 * Vocabulary name for the mod type terms
+	 */
+	public static String vocabName_ModType = "Mod type";
+
+	/**
+	 * Taxonomy term name for the win platform
+	 */
+	public static String taxName_Platform_Win = "Windows";
+	/**
+	 * Taxonomy term name for the mac platform
+	 */
+	public static String taxName_Platform_MacOS = "Mac OS";
+	/**
+	 * Taxonomy term name for platform independent
+	 */
+	public static String taxName_Platform_Both = "Both";
+
+	/**
+	 * Taxonomy term name for package install type
+	 */
+	public static String taxName_InstallType_Package = "Package";
+
+	/**
+	 * Package number at which non-core packages start
+	 */
+	public static int corePackageNumberLimit = 8000;
+
+	/**
+	 * URL of depot
+	 */
+	public static String depotUrl = "http://mods.oni2.net/";
+
+	/**
+	 * @return Taxonomy term names for mods of type Tool
+	 */
+	public static HashSet<String> getTaxonomyName_ModType_Tool() {
+		HashSet<String> res = new HashSet<String>();
+		res.add("Tool");
+		res.add("Patch");
+		return res;
+	}
+
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/DepotManager.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/DepotManager.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/DepotManager.java	(revision 748)
@@ -0,0 +1,370 @@
+package net.oni2.moddepot;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.UnknownHostException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import net.oni2.moddepot.model.File;
+import net.oni2.moddepot.model.Node;
+import net.oni2.moddepot.model.NodeField_Body;
+import net.oni2.moddepot.model.NodeField_Upload;
+import net.oni2.moddepot.model.NodeMod;
+import net.oni2.moddepot.model.TaxonomyTerm;
+import net.oni2.moddepot.model.TaxonomyVocabulary;
+import net.oni2.httpfiledownloader.FileDownloader;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.io.xml.StaxDriver;
+
+/**
+ * @author Christian Illy
+ */
+public class DepotManager {
+	private static DepotManager instance = null;
+
+	private HashMap<Integer, TaxonomyVocabulary> taxonomyVocabulary = new HashMap<Integer, TaxonomyVocabulary>();
+	private HashMap<Integer, TaxonomyTerm> taxonomyTerms = new HashMap<Integer, TaxonomyTerm>();
+
+	private HashMap<Integer, Node> nodes = new HashMap<Integer, Node>();
+	private HashMap<String, HashMap<Integer, Node>> nodesByType = new HashMap<String, HashMap<Integer, Node>>();
+
+	private HashMap<Integer, File> files = new HashMap<Integer, File>();
+
+	/**
+	 * Caching the vocab id for the package type vocabulary
+	 */
+	public int vocabId_type = -1;
+	/**
+	 * Caching the vocab id for the platform vocabulary
+	 */
+	public int vocabId_platform = -1;
+	/**
+	 * Caching the vocab id for the install method vocabulary
+	 */
+	public int vocabId_instmethod = -1;
+
+	/**
+	 * @return Singleton instance
+	 */
+	public static DepotManager getInstance() {
+		if (instance == null)
+			instance = new DepotManager();
+		return instance;
+	}
+
+	/**
+	 * Update local Depot information cache
+	 * 
+	 * @return Update successfully done?
+	 */
+	public boolean updateInformation() {
+		try {
+			java.io.File zipName = new java.io.File(
+					System.getProperty("java.io.tmpdir"), "aei_jsoncache.zip");
+			FileDownloader fd = new FileDownloader(DepotConfig.depotUrl
+					+ "jsoncache/jsoncache.zip?ts="
+					+ (new Date().getTime() / 1000), zipName);
+			fd.start();
+			while (fd.getState() != FileDownloader.EState.FINISHED) {
+				Thread.sleep(50);
+			}
+
+			String jsonVocab = null;
+			String jsonTerms = null;
+			String jsonNodes = null;
+			String jsonFiles = null;
+
+			ZipFile zf = null;
+			try {
+				zf = new ZipFile(zipName);
+
+				for (Enumeration<? extends ZipEntry> e = zf.entries(); e
+						.hasMoreElements();) {
+					ZipEntry ze = e.nextElement();
+					if (!ze.isDirectory()) {
+						BufferedReader input = new BufferedReader(
+								new InputStreamReader(zf.getInputStream(ze)));
+						StringBuffer json = new StringBuffer();
+
+						char data[] = new char[1024];
+						int dataRead;
+						while ((dataRead = input.read(data, 0, 1024)) != -1) {
+							json.append(data, 0, dataRead);
+						}
+
+						if (ze.getName().toLowerCase().contains("vocabulary"))
+							jsonVocab = json.toString();
+						if (ze.getName().toLowerCase().contains("terms"))
+							jsonTerms = json.toString();
+						if (ze.getName().toLowerCase().contains("nodes"))
+							jsonNodes = json.toString();
+						if (ze.getName().toLowerCase().contains("files"))
+							jsonFiles = json.toString();
+					}
+				}
+			} finally {
+				if (zf != null)
+					zf.close();
+				zipName.delete();
+			}
+
+			initVocabulary(new JSONArray(jsonVocab));
+
+			vocabId_type = getVocabulary(DepotConfig.vocabName_ModType)
+					.getVid();
+			vocabId_platform = getVocabulary(DepotConfig.vocabName_Platform)
+					.getVid();
+			vocabId_instmethod = getVocabulary(
+					DepotConfig.vocabName_InstallType).getVid();
+
+			initTerms(new JSONArray(jsonTerms));
+			initFiles(new JSONArray(jsonFiles));
+			initNodes(new JSONArray(jsonNodes));
+
+			return true;
+		} catch (JSONException e) {
+			e.printStackTrace();
+		} catch (IOException e1) {
+			e1.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		return false;
+	}
+
+	private void initFiles(JSONArray ja) throws JSONException {
+		files = new HashMap<Integer, File>();
+		JSONObject jo;
+		for (int i = 0; i < ja.length(); i++) {
+			jo = ja.getJSONObject(i);
+			int fid = jo.getInt("fid");
+
+			File f = new File(jo);
+			files.put(fid, f);
+		}
+	}
+
+	private void initNodes(JSONArray ja) throws JSONException {
+		nodes = new HashMap<Integer, Node>();
+		nodesByType = new HashMap<String, HashMap<Integer, Node>>();
+		JSONObject jo;
+		for (int i = 0; i < ja.length(); i++) {
+			jo = ja.getJSONObject(i);
+
+			int nid = jo.getInt("nid");
+			String type = jo.getString("type");
+
+			Node n = null;
+			if (type.equalsIgnoreCase(DepotConfig.nodeType_Package))
+				n = new NodeMod(jo);
+			else
+				n = new Node(jo);
+
+			if (n.getStatus() > 0) {
+				nodes.put(nid, n);
+				if (!nodesByType.containsKey(type))
+					nodesByType.put(type, new HashMap<Integer, Node>());
+				nodesByType.get(type).put(nid, n);
+			}
+		}
+	}
+
+	private void initTerms(JSONArray ja) throws JSONException {
+		taxonomyTerms.clear();
+		JSONObject jo;
+		for (int i = 0; i < ja.length(); i++) {
+			jo = ja.getJSONObject(i);
+			TaxonomyTerm tt = new TaxonomyTerm(jo);
+			taxonomyTerms.put(tt.getTid(), tt);
+		}
+	}
+
+	private void initVocabulary(JSONArray ja) throws JSONException {
+		taxonomyVocabulary.clear();
+		JSONObject jo;
+		for (int i = 0; i < ja.length(); i++) {
+			jo = ja.getJSONObject(i);
+			TaxonomyVocabulary tv = new TaxonomyVocabulary(jo);
+			taxonomyVocabulary.put(tv.getVid(), tv);
+		}
+	}
+
+	/**
+	 * @return Can we connect to the Depot?
+	 */
+	public boolean checkConnection() {
+		HttpRequestBase httpQuery = null;
+
+		try {
+			DefaultHttpClient httpclient = new DefaultHttpClient();
+			httpQuery = new HttpHead(DepotConfig.depotUrl);
+			HttpResponse response = httpclient.execute(httpQuery);
+			int code = response.getStatusLine().getStatusCode();
+			return (code >= 200) && (code <= 299);
+		} catch (UnknownHostException e) {
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			if (httpQuery != null)
+				httpQuery.releaseConnection();
+		}
+		return false;
+	}
+
+	private TaxonomyVocabulary getVocabulary(String name) {
+		for (TaxonomyVocabulary v : taxonomyVocabulary.values()) {
+			if (v.getName().equalsIgnoreCase(name))
+				return v;
+		}
+		return null;
+	}
+
+	/**
+	 * @param vocabId
+	 *            Get all taxonomy terms of a given vocabulary
+	 * @return TaxTerms
+	 */
+	private Vector<TaxonomyTerm> getTaxonomyTermsByVocabulary(int vocabId) {
+		Vector<TaxonomyTerm> res = new Vector<TaxonomyTerm>();
+		for (TaxonomyTerm t : taxonomyTerms.values()) {
+			if (t.getVid() == vocabId)
+				res.add(t);
+		}
+		return res;
+	}
+
+	/**
+	 * @return All defined types
+	 */
+	public Vector<TaxonomyTerm> getTypes() {
+		return getTaxonomyTermsByVocabulary(vocabId_type);
+	}
+
+	/**
+	 * @param id
+	 *            Get taxonomy term by given ID
+	 * @return TaxTerm
+	 */
+	public TaxonomyTerm getTaxonomyTerm(int id) {
+		return taxonomyTerms.get(id);
+	}
+
+	/**
+	 * Get all nodes of given node type
+	 * 
+	 * @param nodeType
+	 *            Node type
+	 * @return Nodes of type nodeType
+	 */
+	public Vector<Node> getNodesByType(String nodeType) {
+		if (nodesByType.get(nodeType) == null)
+			return new Vector<Node>();
+		return new Vector<Node>(nodesByType.get(nodeType).values());
+	}
+
+	/**
+	 * @return Mod-Nodes
+	 */
+	public Vector<NodeMod> getModPackageNodes() {
+		Vector<NodeMod> result = new Vector<NodeMod>();
+		String instMethName = DepotConfig.taxName_InstallType_Package;
+
+		Vector<Node> files = getNodesByType(DepotConfig.nodeType_Package);
+		for (Node n : files) {
+			if (n instanceof NodeMod) {
+				NodeMod nm = (NodeMod) n;
+				if (nm.getInstallMethod().equalsIgnoreCase(instMethName)) {
+					if (nm.getPackageNumber() >= 0)
+						result.add(nm);
+					else
+						System.err.println("Node " + nm.getNid()
+								+ " does not have a package number!!!");
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @param id
+	 *            ID of file to get
+	 * @return the file
+	 */
+	public File getFile(int id) {
+		return files.get(id);
+	}
+
+	private static XStream getXStream() {
+		XStream xs = new XStream(new StaxDriver());
+		xs.alias("Depot", DepotManager.class);
+		xs.alias("File", net.oni2.moddepot.model.File.class);
+		xs.alias("Node", Node.class);
+		xs.alias("NodeField_Body", NodeField_Body.class);
+		xs.alias("NodeField_Upload", NodeField_Upload.class);
+		xs.alias("NodeMod", NodeMod.class);
+		xs.alias("TaxonomyTerm", TaxonomyTerm.class);
+		xs.alias("TaxonomyVocabulary", TaxonomyVocabulary.class);
+		return xs;
+	}
+
+	/**
+	 * Save Depot cache instance to file
+	 * 
+	 * @param cacheFile
+	 *            File to save to
+	 */
+	public void saveToCacheFile(java.io.File cacheFile) {
+		try {
+			FileOutputStream fos = new FileOutputStream(cacheFile);
+			XStream xs = getXStream();
+			xs.toXML(this, fos);
+			fos.close();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Load cache from file
+	 * 
+	 * @param cacheFile
+	 *            File to load
+	 */
+	public static void loadFromCacheFile(java.io.File cacheFile) {
+		try {
+			FileInputStream fis = new FileInputStream(cacheFile);
+			XStream xs = getXStream();
+			Object obj = xs.fromXML(fis);
+			fis.close();
+			if (obj instanceof DepotManager)
+				instance = (DepotManager) obj;
+		} catch (XStreamException e) {
+		} catch (FileNotFoundException e) {
+		} catch (IOException e) {
+		}
+	}
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/ECompatiblePlatform.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/ECompatiblePlatform.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/ECompatiblePlatform.java	(revision 748)
@@ -0,0 +1,19 @@
+package net.oni2.moddepot;
+
+/**
+ * @author Christian Illy
+ */
+public enum ECompatiblePlatform {
+	/**
+	 * Only for Win
+	 */
+	WIN,
+	/**
+	 * Only for MacOS
+	 */
+	MACOS,
+	/**
+	 * Usable with both platforms
+	 */
+	BOTH
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/JSONHelpers.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/JSONHelpers.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/JSONHelpers.java	(revision 748)
@@ -0,0 +1,30 @@
+package net.oni2.moddepot;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class JSONHelpers {
+	/**
+	 * Return the string associated with the given key or null if the key does
+	 * not exist or does not contain a string
+	 * 
+	 * @param parent
+	 *            Parent JSON object
+	 * @param key
+	 *            Key to look for
+	 * @return Contained string or null
+	 */
+	public static String getStringOrNull(JSONObject parent, String key) {
+		try {
+			Object obj = parent.get(key);
+			if (obj instanceof String)
+				return (String) obj;
+		} catch (JSONException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/File.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/File.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/File.java	(revision 748)
@@ -0,0 +1,112 @@
+package net.oni2.moddepot.model;
+
+import net.oni2.moddepot.JSONHelpers;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class File {
+	private int fid;
+	private int uid; // User ID of uploader
+	private String filename; // Filename
+	private String uri; // Internal URI
+	private String filemime; // Mimetype
+	private int filesize; // Bytes
+	private int status; // ???
+	private long timestamp; // Timestamp of upload
+	private String uri_full; // Full public URI
+	private String target_uri; // ???
+
+	/**
+	 * @param json
+	 *            JSON object of File to parse
+	 * @throws JSONException
+	 *             On key not found / wrong type
+	 */
+	public File(JSONObject json) throws JSONException {
+		fid = json.getInt("fid");
+		uid = json.getInt("uid");
+		filename = JSONHelpers.getStringOrNull(json, "filename");
+		uri = JSONHelpers.getStringOrNull(json, "uri");
+		filemime = JSONHelpers.getStringOrNull(json, "filemime");
+		filesize = json.getInt("filesize");
+		status = json.getInt("status");
+		timestamp = json.getLong("timestamp");
+		uri_full = JSONHelpers.getStringOrNull(json, "uri_full");
+		target_uri = JSONHelpers.getStringOrNull(json, "target_uri");
+	}
+
+	/**
+	 * @return the fid
+	 */
+	public int getFid() {
+		return fid;
+	}
+
+	/**
+	 * @return the uid
+	 */
+	public int getUid() {
+		return uid;
+	}
+
+	/**
+	 * @return the filename
+	 */
+	public String getFilename() {
+		return filename;
+	}
+
+	/**
+	 * @return the uri
+	 */
+	public String getUri() {
+		return uri;
+	}
+
+	/**
+	 * @return the filemime
+	 */
+	public String getFilemime() {
+		return filemime;
+	}
+
+	/**
+	 * @return the filesize
+	 */
+	public int getFilesize() {
+		return filesize;
+	}
+
+	/**
+	 * @return the status
+	 */
+	public int getStatus() {
+		return status;
+	}
+
+	/**
+	 * @return the timestamp
+	 */
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	/**
+	 * @return the uri_full
+	 */
+	public String getUri_full() {
+		return uri_full;
+	}
+
+	/**
+	 * @return the target_uri
+	 */
+	public String getTarget_uri() {
+		return target_uri;
+	}
+
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/Node.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/Node.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/Node.java	(revision 748)
@@ -0,0 +1,274 @@
+package net.oni2.moddepot.model;
+
+import net.oni2.moddepot.JSONHelpers;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class Node {
+	private int uid; // User ID of editor
+	private int nid; // Node ID
+
+	private NodeField_Body body;
+
+	private String data; // ???
+	private int last_comment_uid; // User ID of author of last comment
+	private String last_comment_name; // Name of author of last comment
+	private long last_comment_timestamp; // Timestamp of post time of last
+											// comment
+	private int comment_count; // Number of comments
+	private String type; // Type of node ("story", "page", "mod" ...)
+	private long changed; // Timestamp of last change
+	private String title; // Title of node
+	private long created; // Timestamp of node creation
+	private String name; // Name of user who created the node
+	private String path; // URI of node
+	private int revision_uid; // User ID of author of last revision
+	private int tnid; // ???
+	private int vid; // Revision VID of latest revision
+	private int status; // ??? perhaps published etc?
+	private String log; // ???
+	private int cid; // ???
+	private int picture; // ???
+	private int sticky; // Is sticky on news overview?
+	private int promote; // (???) Is promoted?
+	private long revision_timestamp; // Timestamp of last revision
+	private int translate; // ???
+	private String language; // Languagecode of content
+	private String comment; // ???
+
+	/**
+	 * @param json
+	 *            JSON object of Node to parse
+	 * @throws JSONException
+	 *             On key not found / wrong type
+	 */
+	public Node(JSONObject json) throws JSONException {
+		uid = json.getInt("uid");
+		nid = json.getInt("nid");
+
+		Object bodyObj = json.get("body");
+		if (bodyObj instanceof JSONObject) {
+			JSONObject jBody = ((JSONObject) bodyObj).getJSONArray("und").getJSONObject(0);
+			body = new NodeField_Body(jBody);
+		}
+		data = JSONHelpers.getStringOrNull(json, "data");
+		last_comment_uid = json.getInt("last_comment_uid");
+		last_comment_name = JSONHelpers.getStringOrNull(json,
+				"last_comment_name");
+		last_comment_timestamp = json.getLong("last_comment_timestamp");
+		comment_count = json.getInt("comment_count");
+		type = JSONHelpers.getStringOrNull(json, "type");
+		changed = json.getLong("changed");
+		title = JSONHelpers.getStringOrNull(json, "title");
+		created = json.getLong("created");
+		name = JSONHelpers.getStringOrNull(json, "name");
+		path = JSONHelpers.getStringOrNull(json, "path");
+		revision_uid = json.getInt("revision_uid");
+		tnid = json.getInt("tnid");
+		vid = json.getInt("vid");
+		status = json.getInt("status");
+		log = JSONHelpers.getStringOrNull(json, "log");
+		cid = json.getInt("cid");
+		picture = json.getInt("picture");
+		sticky = json.getInt("sticky");
+		promote = json.getInt("promote");
+		revision_timestamp = json.getLong("revision_timestamp");
+		translate = json.getInt("translate");
+		language = JSONHelpers.getStringOrNull(json, "language");
+		comment = JSONHelpers.getStringOrNull(json, "comment");
+	}
+
+	/**
+	 * @return the uid
+	 */
+	public int getUid() {
+		return uid;
+	}
+
+	/**
+	 * @return the nid
+	 */
+	public int getNid() {
+		return nid;
+	}
+
+	/**
+	 * @return the body
+	 */
+	public NodeField_Body getBody() {
+		return body;
+	}
+
+	/**
+	 * @return the data
+	 */
+	public String getData() {
+		return data;
+	}
+
+	/**
+	 * @return the last_comment_uid
+	 */
+	public int getLast_comment_uid() {
+		return last_comment_uid;
+	}
+
+	/**
+	 * @return the last_comment_name
+	 */
+	public String getLast_comment_name() {
+		return last_comment_name;
+	}
+
+	/**
+	 * @return the last_comment_timestamp
+	 */
+	public long getLast_comment_timestamp() {
+		return last_comment_timestamp;
+	}
+
+	/**
+	 * @return the comment_count
+	 */
+	public int getComment_count() {
+		return comment_count;
+	}
+
+	/**
+	 * @return the type
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * @return the changed
+	 */
+	public long getChanged() {
+		return changed;
+	}
+
+	/**
+	 * @return the title
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * @return the created
+	 */
+	public long getCreated() {
+		return created;
+	}
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @return the path
+	 */
+	public String getPath() {
+		return path;
+	}
+
+	/**
+	 * @return the revision_uid
+	 */
+	public int getRevision_uid() {
+		return revision_uid;
+	}
+
+	/**
+	 * @return the tnid
+	 */
+	public int getTnid() {
+		return tnid;
+	}
+
+	/**
+	 * @return the vid
+	 */
+	public int getVid() {
+		return vid;
+	}
+
+	/**
+	 * @return the status
+	 */
+	public int getStatus() {
+		return status;
+	}
+
+	/**
+	 * @return the log
+	 */
+	public String getLog() {
+		return log;
+	}
+
+	/**
+	 * @return the cid
+	 */
+	public int getCid() {
+		return cid;
+	}
+
+	/**
+	 * @return the picture
+	 */
+	public int getPicture() {
+		return picture;
+	}
+
+	/**
+	 * @return the sticky
+	 */
+	public int getSticky() {
+		return sticky;
+	}
+
+	/**
+	 * @return the promote
+	 */
+	public int getPromote() {
+		return promote;
+	}
+
+	/**
+	 * @return the revision_timestamp
+	 */
+	public long getRevision_timestamp() {
+		return revision_timestamp;
+	}
+
+	/**
+	 * @return the translate
+	 */
+	public int getTranslate() {
+		return translate;
+	}
+
+	/**
+	 * @return the language
+	 */
+	public String getLanguage() {
+		return language;
+	}
+
+	/**
+	 * @return the comment
+	 */
+	public String getComment() {
+		return comment;
+	}
+
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeField_Body.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeField_Body.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeField_Body.java	(revision 748)
@@ -0,0 +1,66 @@
+package net.oni2.moddepot.model;
+
+import net.oni2.moddepot.JSONHelpers;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class NodeField_Body {
+	private String summary;
+	private String value;
+	private String safe_summary;
+	private String safe_value;
+	private int format;
+
+	/**
+	 * @param json
+	 *            JSON object of body-entry to parse
+	 * @throws JSONException
+	 *             On key not found / wrong type
+	 */
+	public NodeField_Body(JSONObject json) throws JSONException {
+		summary = JSONHelpers.getStringOrNull(json, "summary");
+		value = JSONHelpers.getStringOrNull(json, "value");
+		safe_summary = JSONHelpers.getStringOrNull(json, "safe_summary");
+		safe_value = JSONHelpers.getStringOrNull(json, "safe_value");
+		format = json.getInt("format");
+	}
+
+	/**
+	 * @return the summary
+	 */
+	public String getSummary() {
+		return summary;
+	}
+
+	/**
+	 * @return the value
+	 */
+	public String getValue() {
+		return value;
+	}
+
+	/**
+	 * @return the safe_summary
+	 */
+	public String getSafe_summary() {
+		return safe_summary;
+	}
+
+	/**
+	 * @return the safe_value
+	 */
+	public String getSafe_value() {
+		return safe_value;
+	}
+
+	/**
+	 * @return the format
+	 */
+	public int getFormat() {
+		return format;
+	}
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeField_Upload.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeField_Upload.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeField_Upload.java	(revision 748)
@@ -0,0 +1,112 @@
+package net.oni2.moddepot.model;
+
+import net.oni2.moddepot.JSONHelpers;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class NodeField_Upload {
+
+	private long timestamp; // Time of upload
+	private int uid; // User ID of uploader
+	private int fid; // File ID
+	private int filesize; // Size in bytes
+	private String status; // ???
+	private String description;// Description
+	private String filename; // Filename
+	private int display; // isVisible
+	private String filemime; // Mimetype
+	private String uri; // Private URI
+
+	/**
+	 * @param json
+	 *            JSON object of upload-entry to parse
+	 * @throws JSONException
+	 *             On key not found / wrong type
+	 */
+	public NodeField_Upload(JSONObject json) throws JSONException {
+		timestamp = json.getLong("timestamp");
+		uid = json.getInt("uid");
+		fid = json.getInt("fid");
+		filesize = json.getInt("filesize");
+		status = JSONHelpers.getStringOrNull(json, "status");
+		description = JSONHelpers.getStringOrNull(json, "description");
+		filename = JSONHelpers.getStringOrNull(json, "filename");
+		display = json.getInt("display");
+		filemime = JSONHelpers.getStringOrNull(json, "filemime");
+		uri = JSONHelpers.getStringOrNull(json, "uri");
+	}
+
+	/**
+	 * @return the timestamp
+	 */
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	/**
+	 * @return the uid
+	 */
+	public int getUid() {
+		return uid;
+	}
+
+	/**
+	 * @return the fid
+	 */
+	public int getFid() {
+		return fid;
+	}
+
+	/**
+	 * @return the filesize
+	 */
+	public int getFilesize() {
+		return filesize;
+	}
+
+	/**
+	 * @return the status
+	 */
+	public String getStatus() {
+		return status;
+	}
+
+	/**
+	 * @return the description
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * @return the filename
+	 */
+	public String getFilename() {
+		return filename;
+	}
+
+	/**
+	 * @return the display
+	 */
+	public int getDisplay() {
+		return display;
+	}
+
+	/**
+	 * @return the filemime
+	 */
+	public String getFilemime() {
+		return filemime;
+	}
+
+	/**
+	 * @return the uri
+	 */
+	public String getUri() {
+		return uri;
+	}
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeMod.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeMod.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/NodeMod.java	(revision 748)
@@ -0,0 +1,169 @@
+package net.oni2.moddepot.model;
+
+import java.util.HashSet;
+import java.util.Vector;
+
+import net.oni2.moddepot.DepotConfig;
+import net.oni2.moddepot.DepotManager;
+import net.oni2.moddepot.ECompatiblePlatform;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class NodeMod extends Node {
+	private Vector<File> uploads = new Vector<File>();
+
+	private ECompatiblePlatform platform = null;
+	private String installType = null;
+	private HashSet<String> packageType = new HashSet<String>();
+
+	private String creator = "";
+	private String version = "";
+	private int package_number = -1;
+
+	/**
+	 * @param json
+	 *            JSON object of Mod-node to parse
+	 * @throws JSONException
+	 *             On key not found / wrong type
+	 */
+	public NodeMod(JSONObject json) throws JSONException {
+		super(json);
+
+		Object uploadObj = json.get("upload");
+		if (uploadObj instanceof JSONObject) {
+			JSONArray jUploads = ((JSONObject) uploadObj).getJSONArray("und");
+			for (int i = 0; i < jUploads.length(); i++) {
+				NodeField_Upload up = new NodeField_Upload(
+						jUploads.getJSONObject(i));
+				if (up.getDisplay() != 0) {
+					uploads.add(DepotManager.getInstance().getFile(up.getFid()));
+				}
+			}
+		}
+
+		for (Object key : json.keySet()) {
+			String keyS = ((String) key).toLowerCase();
+			Object val = json.get(keyS);
+			if (keyS.startsWith("field_")) {
+				String fName = keyS.substring(keyS.indexOf("_") + 1);
+				String value = "";
+				if (val instanceof JSONObject) {
+					value = ((JSONObject) val).getJSONArray("und")
+							.getJSONObject(0).getString("value");
+				}
+				if (fName.equalsIgnoreCase("version"))
+					version = value;
+				else if (fName.equalsIgnoreCase("creator"))
+					creator = value;
+				else if (fName.equalsIgnoreCase("package_number")) {
+					try {
+						package_number = Integer.parseInt(value);
+					} catch (NumberFormatException e) {
+					}
+				}
+			}
+
+			if (keyS.startsWith("taxonomy_vocabulary_")) {
+				int vid = Integer
+						.parseInt(keyS.substring(keyS.lastIndexOf("_") + 1));
+
+				if (val instanceof JSONObject) {
+					JSONArray ja = ((JSONObject) val).getJSONArray("und");
+
+					if (vid == DepotManager.getInstance().vocabId_platform) {
+						int tid = ja.getJSONObject(0).getInt("tid");
+						String validPlatform = DepotManager.getInstance()
+								.getTaxonomyTerm(tid).getName();
+						if (validPlatform
+								.equalsIgnoreCase(DepotConfig.taxName_Platform_Both))
+							platform = ECompatiblePlatform.BOTH;
+						else if (validPlatform
+								.equalsIgnoreCase(DepotConfig.taxName_Platform_Win))
+							platform = ECompatiblePlatform.WIN;
+						else if (validPlatform
+								.equalsIgnoreCase(DepotConfig.taxName_Platform_MacOS))
+							platform = ECompatiblePlatform.MACOS;
+					} else if (vid == DepotManager.getInstance().vocabId_type) {
+						for (int i = 0; i < ja.length(); i++) {
+							int tid = ja.getJSONObject(i).getInt("tid");
+							packageType.add(DepotManager.getInstance()
+									.getTaxonomyTerm(tid).getName());
+						}
+					} else if (vid == DepotManager.getInstance().vocabId_instmethod) {
+						int tid = ja.getJSONObject(0).getInt("tid");
+						installType = DepotManager.getInstance()
+								.getTaxonomyTerm(tid).getName();
+					}
+				}
+
+			}
+		}
+	}
+
+	/**
+	 * @return the uploads
+	 */
+	public Vector<File> getUploads() {
+		return uploads;
+	}
+
+	/**
+	 * @return Types
+	 */
+	public HashSet<String> getTypes() {
+		return packageType;
+	}
+
+	/**
+	 * @return Install method
+	 */
+	public String getInstallMethod() {
+		return installType;
+	}
+
+	/**
+	 * @return Compatible platform
+	 */
+	public ECompatiblePlatform getPlatform() {
+		return platform;
+	}
+
+	/**
+	 * @return Creator of mod
+	 */
+	public String getCreator() {
+		return creator;
+	}
+
+	/**
+	 * @return Version of mod
+	 */
+	public String getVersion() {
+		return version;
+	}
+
+	/**
+	 * @return Package number
+	 */
+	public int getPackageNumber() {
+		return package_number;
+	}
+
+	/**
+	 * @return Is this mod a tool?
+	 */
+	public boolean isTool() {
+		HashSet<String> types = getTypes();
+		for (String s : DepotConfig.getTaxonomyName_ModType_Tool()) {
+			for (String type : types)
+				if (type.equalsIgnoreCase(s))
+					return true;
+		}
+		return false;
+	}
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/TaxonomyTerm.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/TaxonomyTerm.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/TaxonomyTerm.java	(revision 748)
@@ -0,0 +1,69 @@
+package net.oni2.moddepot.model;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class TaxonomyTerm {
+	private int tid;
+	private int vid;
+	private String name;
+	private String description;
+	private String uri;
+
+	/**
+	 * @param json
+	 *            JSONObject containing the item
+	 * @throws JSONException
+	 *             If a key can't be found
+	 */
+	public TaxonomyTerm(JSONObject json) throws JSONException {
+		tid = json.getInt("tid");
+		vid = json.getInt("vid");
+		name = json.getString("name");
+		description = json.getString("description");
+		uri = json.getString("uri");
+	}
+
+	/**
+	 * @return the term ID (tid)
+	 */
+	public int getTid() {
+		return tid;
+	}
+
+	/**
+	 * @return the vocabulary ID (vid)
+	 */
+	public int getVid() {
+		return vid;
+	}
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @return the description
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * @return the uri
+	 */
+	public String getUri() {
+		return uri;
+	}
+	
+	@Override
+	public String toString() {
+		return getName();
+	}
+}
Index: /java/ModDepotAccess/src/net/oni2/moddepot/model/TaxonomyVocabulary.java
===================================================================
--- /java/ModDepotAccess/src/net/oni2/moddepot/model/TaxonomyVocabulary.java	(revision 748)
+++ /java/ModDepotAccess/src/net/oni2/moddepot/model/TaxonomyVocabulary.java	(revision 748)
@@ -0,0 +1,73 @@
+package net.oni2.moddepot.model;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * @author Christian Illy
+ */
+public class TaxonomyVocabulary {
+	private int vid;
+	private String name;
+	private String machine_name;
+	private String description;
+	private int hierarchy;
+	private String uri;
+
+	/**
+	 * @param json
+	 *            JSONObject containing the item
+	 * @throws JSONException
+	 *             If a key can't be found
+	 */
+	public TaxonomyVocabulary(JSONObject json) throws JSONException {
+		vid = json.getInt("vid");
+		name = json.getString("name");
+		machine_name = json.getString("machine_name");
+		description = json.getString("description");
+		hierarchy = json.getInt("hierarchy");
+		uri = json.getString("uri");
+	}
+
+	/**
+	 * @return the vocabulary ID (vid)
+	 */
+	public int getVid() {
+		return vid;
+	}
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @return the machine_name
+	 */
+	public String getMachine_name() {
+		return machine_name;
+	}
+
+	/**
+	 * @return the description
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * @return the hierarchy level
+	 */
+	public int getHierarchy() {
+		return hierarchy;
+	}
+
+	/**
+	 * @return the uri
+	 */
+	public String getUri() {
+		return uri;
+	}
+}
