001    package net.minecraftforge.common;
002    
003    import java.io.BufferedWriter;
004    import java.io.IOException;
005    import java.util.ArrayList;
006    import java.util.Collection;
007    import java.util.Map;
008    import java.util.Set;
009    import java.util.TreeMap;
010    
011    import com.google.common.base.Splitter;
012    
013    import static net.minecraftforge.common.Configuration.*;
014    
015    public class ConfigCategory implements Map<String, Property>
016    {
017        private String name;
018        private String comment;
019        private ArrayList<ConfigCategory> children = new ArrayList<ConfigCategory>();
020        private Map<String, Property> properties = new TreeMap<String, Property>();
021        public final ConfigCategory parent;
022    
023        public ConfigCategory(String name)
024        {
025            this(name, null);
026        }
027    
028        public ConfigCategory(String name, ConfigCategory parent)
029        {
030            this.name = name;
031            this.parent = parent;
032            if (parent != null)
033            {
034                parent.children.add(this);
035            }
036        }
037    
038        public boolean equals(Object obj)
039        {
040            if (obj instanceof ConfigCategory)
041            {
042                ConfigCategory cat = (ConfigCategory)obj;
043                return name.equals(cat.name) && children.equals(cat.children);  
044            }
045            
046            return false;
047        }
048    
049        public String getQualifiedName()
050        {
051            return getQualifiedName(name, parent);
052        }
053    
054        public static String getQualifiedName(String name, ConfigCategory parent)
055        {
056            return (parent == null ? name : parent.getQualifiedName() + Configuration.CATEGORY_SPLITTER + name);
057        }
058    
059        public ConfigCategory getFirstParent()
060        {
061            return (parent == null ? this : parent.getFirstParent());
062        }
063    
064        public boolean isChild()
065        {
066            return parent != null;
067        }
068    
069        public Map<String, Property> getValues()
070        {
071            return properties;
072        }
073    
074        public void setComment(String comment)
075        {
076            this.comment = comment;
077        }
078    
079        public boolean containsKey(String key)
080        {
081            return properties.containsKey(key);
082        }
083    
084        public Property get(String key)
085        {
086            return properties.get(key);
087        }
088    
089        public void set(String key, Property value)
090        {
091            properties.put(key, value);
092        }
093    
094        public void write(BufferedWriter out, int indent) throws IOException
095        {
096            String pad = getIndent(indent);
097    
098            out.write(pad + "####################" + NEW_LINE);
099            out.write(pad + "# " + name + NEW_LINE);
100    
101            if (comment != null)
102            {
103                out.write(pad + "#===================" + NEW_LINE);
104                Splitter splitter = Splitter.onPattern("\r?\n");
105    
106                for (String line : splitter.split(comment))
107                {
108                    out.write(pad + "# " + line + NEW_LINE);
109                }
110            }
111    
112            out.write(pad + "####################" + NEW_LINE + NEW_LINE);
113    
114            if (!allowedProperties.matchesAllOf(name))
115            {
116                name = '"' + name + '"';
117            }
118    
119            out.write(pad + name + " {" + NEW_LINE);
120    
121            pad = getIndent(indent + 1);
122    
123            Property[] props = properties.values().toArray(new Property[properties.size()]);
124    
125            for (int x = 0; x < props.length; x++)
126            {
127                Property prop = props[x];
128    
129                if (prop.comment != null)
130                {
131                    if (x != 0)
132                    {
133                        out.newLine();
134                    }
135    
136                    Splitter splitter = Splitter.onPattern("\r?\n");
137                    for (String commentLine : splitter.split(prop.comment))
138                    {
139                        out.write(pad + "# " + commentLine + NEW_LINE);
140                    }
141                }
142    
143                String propName = prop.getName();
144    
145                if (!allowedProperties.matchesAllOf(propName))
146                {
147                    propName = '"' + propName + '"';
148                }
149    
150                if (prop.isList())
151                {
152                    out.write(String.format(pad + "%s:%s <" + NEW_LINE, prop.getType().getID(), propName));
153                    pad = getIndent(indent + 2);
154    
155                    for (String line : prop.valueList)
156                    {
157                        out.write(pad + line + NEW_LINE);
158                    }
159    
160                    out.write(getIndent(indent + 1) + " >" + NEW_LINE);
161                }
162                else if (prop.getType() == null)
163                {
164                    out.write(String.format(pad + "%s=%s" + NEW_LINE, propName, prop.value));
165                }
166                else
167                {
168                    out.write(String.format(pad + "%s:%s=%s" + NEW_LINE, prop.getType().getID(), propName, prop.value));
169                }
170            }
171    
172            for (ConfigCategory child : children)
173            {
174                child.write(out, indent + 1);
175            }
176    
177            out.write(getIndent(indent) + "}" + NEW_LINE + NEW_LINE);
178        }
179    
180        private String getIndent(int indent)
181        {
182            StringBuilder buf = new StringBuilder("");
183            for (int x = 0; x < indent; x++)
184            {
185                buf.append("    ");
186            }
187            return buf.toString();
188        }
189    
190    
191        //Map bouncer functions for compatibility with older mods, to be removed once all mods stop using it.
192        @Override public int size(){ return properties.size(); }
193        @Override public boolean isEmpty() { return properties.isEmpty(); }
194        @Override public boolean containsKey(Object key) { return properties.containsKey(key); }
195        @Override public boolean containsValue(Object value){ return properties.containsValue(value); }
196        @Override public Property get(Object key) { return properties.get(key); }
197        @Override public Property put(String key, Property value) { return properties.put(key, value); }
198        @Override public Property remove(Object key) { return properties.remove(key); }
199        @Override public void putAll(Map<? extends String, ? extends Property> m) { properties.putAll(m); }
200        @Override public void clear() { properties.clear(); }
201        @Override public Set<String> keySet() { return properties.keySet(); }
202        @Override public Collection<Property> values() { return properties.values(); }
203        @Override public Set<java.util.Map.Entry<String, Property>> entrySet() { return properties.entrySet(); }
204    
205    }