Subversion Repositories Projects

Rev

Rev 1532 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

package dongfang.mkt.configuration;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class ConfigSet {
        public static final int NUMBER_OF_VARIABLES = 8;
        String name;
        int eepromVersion;
       
        List<Section> declaredSections = new ArrayList<Section>();
        List<ConfigEntry> entries = new ArrayList<ConfigEntry>();

        public static class Section {
                String name, title;
                List<ConfigEntry> entries = new ArrayList<ConfigEntry>();
               
                public Section(String name, String title) {
                        this.name = name;
                        this.title = title;
                }

                public void addConfigEntry(ConfigEntry e) {
                        this.entries.add(e);
                }
               
                public List<ConfigEntry> getEntries() {
                        return entries;
                }
               
                public String getName() { return name; }
                public String getTitle() { return title; }
        }
       
        public static abstract class ConfigEntry {
                String name;

                ConfigEntry(String name) {
                        this.name = name;
                }

                abstract int getByteCount();

                abstract String toStringWithValues();

                abstract void toXML(StringBuilder result);

                abstract int setValue(int[] data, int offset);

                public String getName() {
                        return name;
                }

                public String getSection() {
                        return name;
                }
        }

        public static class ByteEntry extends ConfigEntry {
                ByteEntry(String name, boolean isDynamic) {
                        super(name);
                        this.isDynamic = isDynamic;
                }

                boolean isDynamic;
                int value;

                int getByteCount() {
                        return 1;
                }

                int getValue() {
                        return value;
                }

                int setValue(int[] data, int offset) {
                        this.value = data[offset];
                        return getByteCount();
                }

                String toStringWithValues() {
                        return name + ":\t" + value;
                }

                void toXML(StringBuilder result) {
                        String s_value;
                        int numberOfHighestVariable = 255;
                        int numberOfLowestVariable = numberOfHighestVariable
                                        - NUMBER_OF_VARIABLES;
                        if (isDynamic && value >= numberOfLowestVariable) {
                                s_value = "var" + (value - numberOfLowestVariable);
                        } else
                                s_value = Integer.toString(value);
                        result.append("  <parameter name=\"" + name + "\" value=\""
                                        + s_value + "\"/>\n");
                }
        }

        public static class BitSetEntry extends ConfigEntry {
                BitSetEntry(String name, String[] bitNames) {
                        super(name);
                        this.bitNames = bitNames;
                }

                int value;
                String[] bitNames;

                int getByteCount() {
                        return 1;
                }

                int getValue() {
                        return value;
                }

                int setValue(int[] data, int offset) {
                        value = data[offset];
                        return getByteCount();
                }

                String toStringWithValues() {
                        StringBuilder result = new StringBuilder(name + "\t[");
                        for (int i = 0; i < Math.min(bitNames.length, 8); i++) {
                                if (i != 0)
                                        result.append(", ");
                                result.append(bitNames[i] + ":"
                                                + ((value & (1 << i)) != 0 ? "1" : "0"));
                        }
                        return result.toString();
                }

                void toXML(StringBuilder result) {
                        result.append("  <parameter name=\"" + name + "\">\n");
                        for (int i = 0; i < Math.min(bitNames.length, 8); i++) {
                                result.append("    <bit name=\"" + bitNames[i] + "\" value=\""
                                                + ((value & (1 << i)) != 0 ? "1" : "0") + "\"/>\n");
                        }
                        result.append("  </parameter>\n");
                }
        }

        public static class ArrayEntry extends ConfigEntry {
                int length;
                boolean isDynamic;
                int[] values;

                ArrayEntry(String name, boolean isDynamic, int length) {
                        super(name);
                        this.isDynamic = isDynamic;
                        this.length = length;
                }

                int[] getValue() {
                        return values;
                }

                int setValue(int[] data, int offset) {
                        values = new int[length];
                        System.arraycopy(data, offset, values, 0, length);
                        return length;
                }

                int getByteCount() {
                        return length;
                }

                String toStringWithValues() {
                        StringBuilder result = new StringBuilder(name + ":\t{");
                        for (int i = 0; i < length; i++) {
                                if (i != 0)
                                        result.append(",");
                                result.append(values[i]);
                        }
                        result.append("}");
                        return result.toString();
                }

                void toXML(StringBuilder result) {
                        result.append("  <list name=\"" + name + "\">\n");
                        for (int i = 0; i < length; i++) {
                                result.append("    <entry value=\"" + values[i] + "\"/>\n");
                        }
                        result.append("  </list>\n");
                }
        }

        public List<ConfigEntry> getEntries() {
                return entries;
        }

        public List<Section> getDeclaredSections() {
                return declaredSections;
        }
       
        public void setData(int[] data) {
                int offset = 0;
                for (ConfigEntry entry : entries) {
                        offset += entry.setValue(data, offset);
                }
                StringBuilder sbname = new StringBuilder();
                for (int i = 0; i < 12; i++) {
                        if (data[offset] == 0)
                                break;
                        sbname.append((char) data[offset++]);
                }
                name = sbname.toString();
        }

        public int getByteCount() {
                int result = 0;
                for (ConfigEntry e : entries) {
                        result += e.getByteCount();
                }
                return result;
        }

        public String toStringWithValues() {
                StringBuilder result = new StringBuilder();
                result.append(name + "\n");
                for (ConfigEntry entry : entries) {
                        result.append(entry.toStringWithValues() + "\n");
                }
                return result.toString();
        }

        public String toXML() {
                StringBuilder result = new StringBuilder();
                result.append("<parameterset eepromVersion=\"" + eepromVersion
                                + "\" length=\"" + getByteCount() + "\">\n");
                for (int i = 0; i < entries.size(); i++) {
                        ConfigEntry entry = entries.get(i);
                        entry.toXML(result);
                }
                result.append("</parameterset>\n");
                return result.toString();
        }

        public ConfigSet(int eepromVersion) {
                super();
                this.eepromVersion = eepromVersion;
        }

        // This parses only for the purpose of naming and typing parameter sets!
        // It does not parse the section and default information, which could be
        // useful for GUIs etc.
        public static ConfigSet parseXMLConfigSet(int version) throws IOException {
                String fileName = "configsets/templates/v" + version + ".xml";
                File f = new File(fileName);
                DocumentBuilderFactory saxfac = DocumentBuilderFactory.newInstance();
                saxfac.setValidating(false);
                try {
                        DocumentBuilder bldr = saxfac.newDocumentBuilder();
                        Document doc = bldr.parse(f);
                        XPath xpath = XPathFactory.newInstance().newXPath();

                        String s_eepromVersion = xpath.evaluate(
                                        "/parametertemplate/@eepromVersion", doc);
                        int eepromVersion = Integer.parseInt(s_eepromVersion);

                        if (eepromVersion != version) {
                                throw new IOException(
                                                "Version mismatch between file name ("
                                                                + fileName
                                                                + ") and the version in the parametertemplate/@eepromVersion attribute("
                                                                + s_eepromVersion + ")");
                        }

                        ConfigSet result = new ConfigSet(eepromVersion);

                        NodeList sectionNodes = (NodeList) xpath.evaluate(
                                        "/parametertemplate/section", doc, XPathConstants.NODESET);

                        for (int i = 0; i < sectionNodes.getLength(); i++) {
                                Element sectionNode = (Element) sectionNodes.item(i);
                                Section section = new Section(sectionNode.getAttribute("name"), sectionNode.getAttribute("title"));
                                result.declaredSections.add(section);
                       
                        NodeList parameterNodes = (NodeList) xpath.evaluate(
                                        "parameter", sectionNode, XPathConstants.NODESET);

                        for (int j=0; j<parameterNodes.getLength(); j++) {
                                Element parameterNode = (Element) parameterNodes.item(j);

                                ConfigEntry entry;
                               
                                if (!sectionNode.hasAttribute("name")) {
                                        throw new IOException("A parameter element (the " + j
                                                        + "th in section "+sectionNode.getAttribute("name")+") had no name attribute!");
                                }

                                String s_name = parameterNode.getAttribute("name");
                                String s_type;

                                if (parameterNode.hasAttribute("type")) {
                                        s_type = parameterNode.getAttribute("type");
                                } else {
                                        s_type = "static";
                                }

                                if ("static".equals(s_type)) {
                                        entry = new ConfigSet.ByteEntry(s_name, false);
                                } else if ("dynamic".equals(s_type)) {
                                        entry = new ConfigSet.ByteEntry(s_name, true);
                                } else if ("bitset".equals(s_type)) {
                                        NodeList bitNodes = (NodeList) xpath.evaluate("bit", parameterNode, XPathConstants.NODESET);
                                        String[] bitNames = new String[8];
                                        for (int k=0; k<8; k++) {
                                                Element bitNode = (Element) bitNodes.item(k);
                                                if (bitNode != null) {
                                                        bitNames[k] = bitNode.getAttribute("name");
                                                } else {
                                                        bitNames[k] = "Unused";
                                                }
                                        }
                                        entry = new ConfigSet.BitSetEntry(s_name, bitNames);
                                } else {
                                        throw new IOException("Unknown parameter type: " + s_type);
                                }
                               
                                result.entries.add(entry);
                                section.addConfigEntry(entry);
                        }
                        }
                        result.name = "" + version;
                        return result;
                } catch (IOException ex) {
                        throw ex;
                } catch (XPathExpressionException ex) {
                        throw new IOException(ex);
                } catch (SAXException ex) {
                        throw new IOException(ex);
                } catch (ParserConfigurationException ex) {
                        throw new IOException(ex);
                }
        }
}