package dongfang.mkt.configuration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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 =
"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(
"/parameterconfig/@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 parameterconfig/@eepromVersion attribute("
+ s_eepromVersion +
")");
}
ConfigSet result =
new ConfigSet
(eepromVersion
);
NodeList sectionNodes =
(NodeList) xpath.
evaluate(
"/section", doc,
XPathConstants.
NODESET);
for (int i =
0; i
< sectionNodes.
getLength(); i++
) {
Element e =
(Element) sectionNodes.
item(i
);
Section section =
new Section
(e.
getAttribute("name"), e.
getAttribute("title"));
result.
declaredSections.
add(section
);
}
NodeList parameterNodes =
(NodeList) xpath.
evaluate(
"/parameterconfig/parameter", doc,
XPathConstants.
NODESET);
Section rest =
new Section
("others",
"Entries without a declared section");
for (int i =
0; i
< parameterNodes.
getLength(); i++
) {
Element e =
(Element) parameterNodes.
item(i
);
Map<String, Section
> sectionMap =
new HashMap<String, Section
>();
ConfigEntry entry
;
if (!e.
hasAttribute("name")) {
throw new IOException("A parameter element (the " + i
+
"th) had no name attribute!");
}
String s_name = e.
getAttribute("name");
String s_section = e.
getAttribute("section");
String s_type
;
if (e.
hasAttribute("type")) {
s_type = e.
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", e,
XPathConstants.
NODESET);
String[] bitNames =
new String[8];
for (int j =
0; j
< 8; j++
) {
Element bitNode =
(Element) bitNodes.
item(j
);
if (bitNode
!=
null) {
bitNames
[j
] = bitNode.
getAttribute("name");
} else {
bitNames
[j
] =
"Unused";
}
}
entry =
new ConfigSet.
BitSetEntry(s_name,
bitNames
);
} else {
throw new IOException("Unknown parameter type: " + s_type
);
}
result.
entries.
add(entry
);
Section section = sectionMap.
get(s_section
);
if (section==
null) section = rest
;
section.
addConfigEntry(entry
);
}
if (!rest.
getEntries().
isEmpty()) {
result.
declaredSections.
add(rest
);
}
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
);
}
}
}