Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Group.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Group.java	(revision 14326)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Group.java	(revision 14326)
@@ -0,0 +1,104 @@
+package org.openstreetmap.josm.plugins.tageditor.preset;
+
+import java.awt.Image;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.plugins.tageditor.util.IndentWriter;
+
+
+/**
+ * Group represents a named group of preset items. Groups can be nested.
+ * 
+ * @author Gubaer
+ *
+ */
+public class Group implements INameIconProvider {
+	
+	static private Logger logger = Logger.getLogger(Group.class.getName());
+	
+	
+	private String name;
+	private String iconName;
+	private ImageIcon icon;
+	private List<Item> items = null;
+	
+	public Group() {
+		items = new ArrayList<Item>();
+	}
+	
+	public Group(String name) {
+		this();
+		setName(name);
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getIconName() {
+		return iconName;
+	}
+
+	public void setIconName(String iconName) {
+		this.iconName = iconName;
+	}
+	
+	public Icon getIcon() {
+		if (icon == null) {
+			// load the icon from the JOSM resources, use Main classloader
+			// for loading 
+			URL url = Main.class.getResource("/images/" + getIconName());
+			if (url == null) {
+				logger.warning("failed to create URL for resource 'images/" + getIconName() + "'");
+				this.icon = null;
+			} else {
+				icon =new ImageIcon(url);
+				Image i = icon.getImage().getScaledInstance(16, 16, Image.SCALE_DEFAULT);
+				icon = new ImageIcon(i);
+
+			}
+		}
+		return icon;
+	}
+	
+	public void addItem(Item item) {
+		item.setParent(this);
+		items.add(item);
+	}
+	
+	public void removeItem(Item item) {
+		items.remove(item);
+	}
+	
+	public List<Item> getItems() {
+		return items; 
+	}
+	
+	public void dump(IndentWriter writer) throws IOException {
+		writer.indent();
+		writer.write("<group ");
+		writer.write(String.format("name=\"%s\" ", name));
+		writer.write(String.format("iconName=\"%s\" ", iconName));
+		writer.write(">");
+		writer.write("\n");
+		writer.incLevel();
+		for(Item item: items) {
+			item.dump(writer);
+		}
+		writer.decLevel();
+		writer.writeLine("</group>");
+	} 
+	
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/INameIconProvider.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/INameIconProvider.java	(revision 14326)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/INameIconProvider.java	(revision 14326)
@@ -0,0 +1,9 @@
+package org.openstreetmap.josm.plugins.tageditor.preset;
+
+import javax.swing.Icon;
+
+public interface INameIconProvider {
+
+	public String getName();
+	public Icon  getIcon();
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Item.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Item.java	(revision 14326)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Item.java	(revision 14326)
@@ -0,0 +1,127 @@
+package org.openstreetmap.josm.plugins.tageditor.preset;
+
+import java.awt.Image;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.plugins.tageditor.util.IndentWriter;
+
+import sun.java2d.loops.ScaledBlit;
+
+
+public class Item  implements INameIconProvider {
+
+	private static Logger logger = Logger.getLogger(Item.class.getName());
+	
+	private String name;
+	private String iconName;
+	private ImageIcon icon;
+	private String label;
+	private List<Tag> tags;
+	private Group parent;
+
+	public Item() {	
+		tags = new ArrayList<Tag>();
+	}
+	
+	public Group getParent() {
+		return parent;
+	}
+
+	public void setParent(Group parent) {
+		this.parent = parent;
+	}
+
+	
+	public String getLabel() {
+		return label;
+	}
+
+	public void setLabel(String label) {
+		this.label = label;
+	}
+
+	
+	public Item(String name) {
+		setName(name);
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getIconName() {
+		return iconName;
+	}
+
+	public void setIconName(String iconName) {
+		this.iconName = iconName;
+	}
+	
+	public Icon getIcon() {
+		if (icon == null) {
+			// load the icon from the JOSM resources, use Main classloader
+			// for loading 
+			URL url = Main.class.getResource("/images/" + getIconName());
+			if (url == null) {
+				logger.warning("failed to create URL for resource 'images/" + getIconName() + "'");
+				icon = null;
+			} else {
+				icon =new ImageIcon(url);
+			}
+			Image i = icon.getImage().getScaledInstance(16, 16, Image.SCALE_DEFAULT);
+			icon = new ImageIcon(i);
+			
+		}
+		return icon;	
+	}
+	
+	public void addTag(Tag tag) {
+		tags.add(tag);
+	}
+	
+	public List<Tag> getTags() {
+		return tags; 
+	}
+	
+	public void dump(IndentWriter writer) throws IOException {
+		writer.indent();
+		writer.write("<item ");
+		writer.write(String.format("name=\"%s\" ", name));
+		writer.write(String.format("label=\"%s\" ", label));
+		writer.write(String.format("iconName=\"%s\" ", iconName));
+		writer.write(">");
+		writer.write("\n");
+		writer.incLevel();
+		for(Tag tag: tags) {
+			tag.dump(writer);
+		}
+		writer.decLevel();
+		writer.writeLine("</item>");
+	} 
+	
+	public String toString() {
+		StringBuilder builder  = new StringBuilder();
+		builder.append("[")
+			.append(getClass().getName())
+			.append(":")
+			.append("name=")
+			.append(name)
+			.append("]");
+		
+		return builder.toString();
+	}
+	
+	
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Presets.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Presets.java	(revision 14326)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Presets.java	(revision 14326)
@@ -0,0 +1,144 @@
+package org.openstreetmap.josm.plugins.tageditor.preset;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.io.MirroredInputStream;
+import org.openstreetmap.josm.plugins.tageditor.preset.io.Parser;
+import org.openstreetmap.josm.plugins.tageditor.preset.io.PresetIOException;
+import org.openstreetmap.josm.plugins.tageditor.util.IndentWriter;
+
+
+public class Presets {
+	private static Logger logger = Logger.getLogger(Presets.class.getName());
+	
+	private static Presets presets = null;
+	
+	
+	static public void initPresets()  {
+		
+		presets = new Presets();
+		
+		// code copied from org.openstreetmap.josm.gui.tagging.TaggingPreset
+		// and slightly modified
+		//
+		
+		String allTaggingPresets = Main.pref.get("taggingpreset.sources");
+
+        if (Main.pref.getBoolean("taggingpreset.enable-defaults", true))
+        {
+            allTaggingPresets = "resource://presets/presets.xml"
+            + (allTaggingPresets != null ? ";"+allTaggingPresets : "");
+        }
+
+        for(String source : allTaggingPresets.split(";"))
+        {
+        	logger.log(Level.INFO, String.format("starting to read presets from source '%1$s'", source));
+            try {
+                MirroredInputStream s = new MirroredInputStream(source);
+                InputStreamReader r;
+                try
+                {
+                    r = new InputStreamReader(s, "UTF-8");
+                }
+                catch (UnsupportedEncodingException e)
+                {
+                    r = new InputStreamReader(s);
+                }
+                presets = loadPresets(r,presets);
+               
+            } catch(PresetIOException e) {
+            	logger.log(Level.SEVERE, tr("Could not read tagging preset source: {0}", source),e);
+            	JOptionPane.showMessageDialog(Main.parent, tr("Could not read tagging preset source: {0}",source));	
+            } catch (IOException e) {
+                e.printStackTrace();
+                JOptionPane.showMessageDialog(Main.parent, tr("Could not read tagging preset source: {0}",source));
+            } 
+        }		 
+	}
+	
+	static public Presets loadPresets(URL from) throws PresetIOException {
+		try {
+			URLConnection con = from.openConnection();
+			con.connect();
+			Reader reader = new InputStreamReader(
+				con.getInputStream()
+			);
+			return loadPresets(reader,null);
+		} catch(Exception e) {
+			logger.log(Level.SEVERE, "exception caught while loading preset file",e);
+			throw new PresetIOException(e);
+		}
+		
+	}
+	
+	static public Presets loadPresets(Reader reader, Presets p) throws PresetIOException {
+		try{
+			Parser parser = new Parser();
+			parser.setReader(reader);
+			parser.setPresets(p);
+			parser.parse();
+			return parser.getPresets();
+		} catch(Exception e) {
+			logger.log(Level.SEVERE, "exception caught while loading presets",e);
+			throw new PresetIOException(e);
+		}
+	}
+	
+	
+	
+	
+	static public Presets getPresets() {
+		if (presets == null) {
+			initPresets();
+		}
+		return presets;  
+	}
+	
+	
+	private List<Group> groups;
+	
+	public Presets() {
+		groups = new ArrayList<Group>();
+	}
+	
+	public void addGroup(Group group) {
+		groups.add(group);
+	}
+	
+	public void removeGroup(Group group) {
+		groups.remove(group);
+	}
+	
+	public void dump(IndentWriter writer) throws IOException {
+		writer.indent();
+		writer.write("<presets>\n");
+		writer.incLevel();
+		for(Group group: groups) {
+			group.dump(writer);
+		}
+		writer.decLevel();
+		writer.indent();
+		writer.write("</presets>");
+	} 
+	
+	public List<Group> getGroups() {
+		return groups;
+	}
+
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Tag.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Tag.java	(revision 14326)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Tag.java	(revision 14326)
@@ -0,0 +1,67 @@
+package org.openstreetmap.josm.plugins.tageditor.preset;
+
+import java.io.IOException;
+
+import org.openstreetmap.josm.plugins.tageditor.util.IndentWriter;
+
+
+public class Tag {
+	private String key;
+	private String value;
+	private String displayName;
+	private boolean optional = false;
+	
+	public Tag() {		
+	}
+
+	public String getKey() {
+		return key;
+	}
+
+	public void setKey(String key) {
+		this.key = key;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+
+	public String getDisplayName() {
+		return displayName;
+	}
+
+	public void setDisplayName(String displayName) {
+		this.displayName = displayName;
+	}
+
+	public boolean isOptional() {
+		return optional;
+	}
+
+	public void setOptional(boolean optional) {
+		this.optional = optional;
+	}
+	
+	
+	public void dump(IndentWriter writer) throws IOException {
+		writer.indent();
+		writer.write("<tag ");
+		writer.write(String.format("key=\"%s\" ", key));
+		writer.write(String.format("optional=\"%s\" ", Boolean.toString(optional)));
+		if (value != null) {
+			writer.write(String.format("value=\"%s\" ", value));
+		}
+		writer.write(String.format("displayName=\"%s\" ", displayName));
+		writer.write("/>");
+		writer.write("\n");
+	}
+	 
+	
+	
+	
+
+}
