Subversion Repositories Projects

Rev

Rev 1559 | 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 StaticByteEntry extends ConfigEntry {
                StaticByteEntry(String name) {
                        super(name);
                }

                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;
                        s_value = Integer.toString(value);
                        result.append("  <parameter name=\"" + name + "\" value=\""
                                        + s_value + "\"/>\n");
                }
        }

        public static class DynamicByteEntry extends StaticByteEntry {
                int minValue = 0;
                int maxValue = 255;
                String staticCodeName;
                String dynamicCodeName;
               
                DynamicByteEntry(String name) {
                        super(name);
                }

                int getMinValue() {
                        return minValue;
                }

                int getMaxValue() {
                        return maxValue;
                }

                void setMinValue(int minValue) {
                        this.minValue = minValue;
                }

                void setMaxValue(int maxValue) {
                        this.maxValue = maxValue;
                }

                String getStaticCodeName() {
                        return staticCodeName;
                }

                String getDynamicCodeName() {
                        return dynamicCodeName;
                }

                void setStaticCodeName(String staticCodeName) {
                        this.staticCodeName = staticCodeName;
                }

                void setDynamicCodeName(String dynamicCodeName) {
                        this.dynamicCodeName = dynamicCodeName;
                }

                void toXML(StringBuilder result) {
                        String s_value;
                        int numberOfLowestVariable = 256 - NUMBER_OF_VARIABLES;
                        if (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.StaticByteEntry(s_name);
                                        } else if ("dynamic".equals(s_type)) {
                                                ConfigSet.DynamicByteEntry de = new ConfigSet.DynamicByteEntry(s_name);
                                                if (parameterNode.hasAttribute("minValue")) {
                                                        de.setMinValue(Integer.parseInt(parameterNode.getAttribute("minValue")));
                                                }
                                                if (parameterNode.hasAttribute("maxValue")) {
                                                        de.setMinValue(Integer.parseInt(parameterNode.getAttribute("maxValue")));
                                                }
                                                if (parameterNode.hasAttribute("staticCodeName")) {
                                                        de.setStaticCodeName(parameterNode.getAttribute("staticCodeName"));
                                                } else de.setStaticCodeName(de.getName());
                                                if (parameterNode.hasAttribute("dynamicCodeName")) {
                                                        de.setDynamicCodeName(parameterNode.getAttribute("dynamicCodeName"));
                                                } else de.setDynamicCodeName(de.getName());
                                                entry = de;
                                        } 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);
                }
        }

        public String generateDynamicSubstitutionCode() {
                StringBuilder result = new StringBuilder(
                                "const MMXLATION XLATIONS[] = {\n");
                boolean hasEntries = false;
                for (ConfigEntry entry : entries) {
                        if (entry instanceof ConfigSet.DynamicByteEntry) {
                                if (hasEntries)
                                        result.append(",\n");
                                else
                                        hasEntries = true;
                                ConfigSet.DynamicByteEntry de = (ConfigSet.DynamicByteEntry) entry;
                                result.append("{offsetof(ParamSet_t, ");
                                result.append(de.getStaticCodeName());
                                result.append("), offsetof(DynamicParams_t, ");
                                result.append(de.getDynamicCodeName());
                                result.append("),");
                                result.append(Integer.toString(de.getMinValue()));
                                result.append(",");
                                result.append(Integer.toString(de.getMaxValue()));
                                result.append("}");
                        }
                }
                result.append("};");
                return result.toString();
        }
}