// Path: src/com/ganggarrison/gmdec/ResourceTreeEntry.java
// public class ResourceTreeEntry {
// 	public String name;
// 	public String filename;
// 	public Type type;
// 
// 	public ResourceTreeEntry(String name, String filename, Type type) {
// 		this.name = name;
// 		this.filename = filename;
// 		this.type = type;
// 	}
// 
// 	public ResourceTreeEntry() {
// 	}
// 
// 	public String getFilename() {
// 		String result;
// 		if (filename != null && !filename.isEmpty()) {
// 			result = filename;
// 		} else {
// 			result = name;
// 		}
// 		if (FileTools.isGoodFilename(result)) {
// 			return result;
// 		} else {
// 			throw new IllegalStateException("Bad filename in resource list: " + result);
// 		}
// 	}
// 
// 	public static enum Type {
// 		RESOURCE, GROUP
// 	}
// }
// 
// Path: src/com/ganggarrison/gmdec/ResourceTreeEntry.java
// public static enum Type {
// 	RESOURCE, GROUP
// }
// 
// Path: src/com/ganggarrison/gmdec/dupes/OrderPreservingDupeRemoval.java
// public class OrderPreservingDupeRemoval {
// 	public static <Item> void perform(ItemAccessor<Item> accessor) {
// 		int changed = 0;
// 
// 		List<Item> items = accessor.getItems();
// 		List<Item> invalidIdItems = new ArrayList<Item>();
// 		TreeMultiMap<Integer, Item> itemsById = new TreeMultiMap<Integer, Item>();
// 
// 		for (Item item : items) {
// 			Integer id = accessor.getId(item);
// 			if (id == null) {
// 				invalidIdItems.add(item);
// 			} else {
// 				itemsById.add(id, item);
// 			}
// 		}
// 
// 		int nextFreeItemId = accessor.getFirstValidId();
// 		for (Map.Entry<Integer, List<Item>> entry : itemsById) {
// 			for (Item item : entry.getValue()) {
// 				int id = entry.getKey();
// 				if (id >= nextFreeItemId) {
// 					nextFreeItemId = id + 1;
// 				} else {
// 					accessor.setId(item, nextFreeItemId++);
// 					changed++;
// 				}
// 			}
// 		}
// 
// 		for (Item item : invalidIdItems) {
// 			accessor.setId(item, nextFreeItemId++);
// 		}
// 
// 		accessor.setMaxId(nextFreeItemId - 1);
// 
// 		if (changed > 0) {
// 			System.err.println("INFO: " + changed + " duplicate " + accessor.getItemName() + " IDs have been changed.");
// 		}
// 		if (invalidIdItems.size() > 0 && accessor.informAboutNewIds()) {
// 			System.err.println("INFO: " + invalidIdItems.size() + " new " + accessor.getItemName()
// 					+ " IDs have been assigned.");
// 		}
// 	}
// }
// 
// Path: src/com/ganggarrison/gmdec/dupes/ResourceAccessor.java
// public class ResourceAccessor<T extends InstantiableResource<T, ?>> implements ItemAccessor<T> {
// 	private List<T> resources;
// 
// 	public ResourceAccessor(List<T> resources) {
// 		this.resources = resources;
// 	}
// 
// 	@Override
// 	public List<T> getItems() {
// 		return Collections.unmodifiableList(resources);
// 	}
// 
// 	@Override
// 	public Integer getId(T item) {
// 		int id = item.getId();
// 		return id >= 0 ? id : null;
// 	}
// 
// 	@Override
// 	public void setId(T item, int id) {
// 		item.setId(id);
// 	}
// 
// 	@Override
// 	public int getFirstValidId() {
// 		return 0;
// 	}
// 
// 	@Override
// 	public void setMaxId(int id) {
// 		// The resource lists calculate that automatically.
// 	}
// 
// 	@Override
// 	public String getItemName() {
// 		if (resources.isEmpty()) {
// 			return "Resource";
// 		} else {
// 			return resources.get(0).getClass().getSimpleName();
// 		}
// 	}
// 
// 	@Override
// 	public boolean informAboutNewIds() {
// 		if (resources.isEmpty()) {
// 			return false;
// 		} else {
// 			if (resources.get(0) instanceof GmObject) {
// 				return GmkSplitter.preserveIds == IdPreservation.ALL || GmkSplitter.preserveIds == IdPreservation.OBJECTS;
// 			} else {
// 				return GmkSplitter.preserveIds == IdPreservation.ALL;
// 			}
// 		}
// 	}
// }


import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.lateralgm.components.impl.ResNode;
import org.lateralgm.file.GmFile;
import org.lateralgm.file.ResourceList;
import org.lateralgm.resources.InstantiableResource;
import org.lateralgm.resources.Resource;
import com.ganggarrison.gmdec.ResourceTreeEntry;
import com.ganggarrison.gmdec.ResourceTreeEntry.Type;
import com.ganggarrison.gmdec.dupes.OrderPreservingDupeRemoval;
import com.ganggarrison.gmdec.dupes.ResourceAccessor;
package com.ganggarrison.gmdec.files;




public abstract class ResourceFormat<T extends InstantiableResource<T, ?>> extends FileTreeFormat<T> {
	@Override
	public void addResToTree(T resource, ResNode parent) {
		ResNode child = new ResNode(resource.getName(),
				ResNode.STATUS_SECONDARY, resource.getClass(), resource.reference);
		parent.add(child);
	}

	@Override
	public void addAllResourcesToGmFile(List<T> resources, GmFile gmf) {
		if (resources.isEmpty()) {
			return;
		}
		@SuppressWarnings("unchecked")
		Class<T> kind = (Class<T>) resources.get(0).getClass();

		checkDuplicateNames(resources, kind);

		// Take care of dupes and unassigned IDs
		ResourceAccessor<T> accessor = new ResourceAccessor<T>(resources);
// Path: src/com/ganggarrison/gmdec/ResourceTreeEntry.java
// public class ResourceTreeEntry {
// 	public String name;
// 	public String filename;
// 	public Type type;
// 
// 	public ResourceTreeEntry(String name, String filename, Type type) {
// 		this.name = name;
// 		this.filename = filename;
// 		this.type = type;
// 	}
// 
// 	public ResourceTreeEntry() {
// 	}
// 
// 	public String getFilename() {
// 		String result;
// 		if (filename != null && !filename.isEmpty()) {
// 			result = filename;
// 		} else {
// 			result = name;
// 		}
// 		if (FileTools.isGoodFilename(result)) {
// 			return result;
// 		} else {
// 			throw new IllegalStateException("Bad filename in resource list: " + result);
// 		}
// 	}
// 
// 	public static enum Type {
// 		RESOURCE, GROUP
// 	}
// }
// 
// Path: src/com/ganggarrison/gmdec/ResourceTreeEntry.java
// public static enum Type {
// 	RESOURCE, GROUP
// }
// 
// Path: src/com/ganggarrison/gmdec/dupes/OrderPreservingDupeRemoval.java
// public class OrderPreservingDupeRemoval {
// 	public static <Item> void perform(ItemAccessor<Item> accessor) {
// 		int changed = 0;
// 
// 		List<Item> items = accessor.getItems();
// 		List<Item> invalidIdItems = new ArrayList<Item>();
// 		TreeMultiMap<Integer, Item> itemsById = new TreeMultiMap<Integer, Item>();
// 
// 		for (Item item : items) {
// 			Integer id = accessor.getId(item);
// 			if (id == null) {
// 				invalidIdItems.add(item);
// 			} else {
// 				itemsById.add(id, item);
// 			}
// 		}
// 
// 		int nextFreeItemId = accessor.getFirstValidId();
// 		for (Map.Entry<Integer, List<Item>> entry : itemsById) {
// 			for (Item item : entry.getValue()) {
// 				int id = entry.getKey();
// 				if (id >= nextFreeItemId) {
// 					nextFreeItemId = id + 1;
// 				} else {
// 					accessor.setId(item, nextFreeItemId++);
// 					changed++;
// 				}
// 			}
// 		}
// 
// 		for (Item item : invalidIdItems) {
// 			accessor.setId(item, nextFreeItemId++);
// 		}
// 
// 		accessor.setMaxId(nextFreeItemId - 1);
// 
// 		if (changed > 0) {
// 			System.err.println("INFO: " + changed + " duplicate " + accessor.getItemName() + " IDs have been changed.");
// 		}
// 		if (invalidIdItems.size() > 0 && accessor.informAboutNewIds()) {
// 			System.err.println("INFO: " + invalidIdItems.size() + " new " + accessor.getItemName()
// 					+ " IDs have been assigned.");
// 		}
// 	}
// }
// 
// Path: src/com/ganggarrison/gmdec/dupes/ResourceAccessor.java
// public class ResourceAccessor<T extends InstantiableResource<T, ?>> implements ItemAccessor<T> {
// 	private List<T> resources;
// 
// 	public ResourceAccessor(List<T> resources) {
// 		this.resources = resources;
// 	}
// 
// 	@Override
// 	public List<T> getItems() {
// 		return Collections.unmodifiableList(resources);
// 	}
// 
// 	@Override
// 	public Integer getId(T item) {
// 		int id = item.getId();
// 		return id >= 0 ? id : null;
// 	}
// 
// 	@Override
// 	public void setId(T item, int id) {
// 		item.setId(id);
// 	}
// 
// 	@Override
// 	public int getFirstValidId() {
// 		return 0;
// 	}
// 
// 	@Override
// 	public void setMaxId(int id) {
// 		// The resource lists calculate that automatically.
// 	}
// 
// 	@Override
// 	public String getItemName() {
// 		if (resources.isEmpty()) {
// 			return "Resource";
// 		} else {
// 			return resources.get(0).getClass().getSimpleName();
// 		}
// 	}
// 
// 	@Override
// 	public boolean informAboutNewIds() {
// 		if (resources.isEmpty()) {
// 			return false;
// 		} else {
// 			if (resources.get(0) instanceof GmObject) {
// 				return GmkSplitter.preserveIds == IdPreservation.ALL || GmkSplitter.preserveIds == IdPreservation.OBJECTS;
// 			} else {
// 				return GmkSplitter.preserveIds == IdPreservation.ALL;
// 			}
// 		}
// 	}
// }


// Path: src/com/ganggarrison/gmdec/files/ResourceFormat.java
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.lateralgm.components.impl.ResNode;
import org.lateralgm.file.GmFile;
import org.lateralgm.file.ResourceList;
import org.lateralgm.resources.InstantiableResource;
import org.lateralgm.resources.Resource;
import com.ganggarrison.gmdec.ResourceTreeEntry;
import com.ganggarrison.gmdec.ResourceTreeEntry.Type;
import com.ganggarrison.gmdec.dupes.OrderPreservingDupeRemoval;
import com.ganggarrison.gmdec.dupes.ResourceAccessor;

package com.ganggarrison.gmdec.files;




public abstract class ResourceFormat<T extends InstantiableResource<T, ?>> extends FileTreeFormat<T> {
	@Override
	public void addResToTree(T resource, ResNode parent) {
		ResNode child = new ResNode(resource.getName(),
				ResNode.STATUS_SECONDARY, resource.getClass(), resource.reference);
		parent.add(child);
	}

	@Override
	public void addAllResourcesToGmFile(List<T> resources, GmFile gmf) {
		if (resources.isEmpty()) {
			return;
		}
		@SuppressWarnings("unchecked")
		Class<T> kind = (Class<T>) resources.get(0).getClass();

		checkDuplicateNames(resources, kind);

		// Take care of dupes and unassigned IDs
		ResourceAccessor<T> accessor = new ResourceAccessor<T>(resources);
		OrderPreservingDupeRemoval.perform(accessor);