📄 xfaform.java
字号:
/**
* A structure to store each part of a SOM name and link it to the next part
* beginning from the lower hierarchie.
*/
public static class InverseStore {
protected ArrayList part = new ArrayList();
protected ArrayList follow = new ArrayList();
/**
* Gets the full name by traversing the hiearchie using only the
* index 0.
* @return the full name
*/
public String getDefaultName() {
InverseStore store = this;
while (true) {
Object obj = store.follow.get(0);
if (obj instanceof String)
return (String)obj;
store = (InverseStore)obj;
}
}
/**
* Search the current node for a similar name. A similar name starts
* with the same name but has a differnt index. For example, "detail[3]"
* is similar to "detail[9]". The main use is to discard names that
* correspond to out of bounds records.
* @param name the name to search
* @return <CODE>true</CODE> if a similitude was found
*/
public boolean isSimilar(String name) {
int idx = name.indexOf('[');
name = name.substring(0, idx + 1);
for (int k = 0; k < part.size(); ++k) {
if (((String)part.get(k)).startsWith(name))
return true;
}
return false;
}
}
/**
* Another stack implementation. The main use is to facilitate
* the porting to other languages.
*/
public static class Stack2 extends ArrayList {
private static final long serialVersionUID = -7451476576174095212L;
/**
* Looks at the object at the top of this stack without removing it from the stack.
* @return the object at the top of this stack
*/
public Object peek() {
if (size() == 0)
throw new EmptyStackException();
return get(size() - 1);
}
/**
* Removes the object at the top of this stack and returns that object as the value of this function.
* @return the object at the top of this stack
*/
public Object pop() {
if (size() == 0)
throw new EmptyStackException();
Object ret = get(size() - 1);
remove(size() - 1);
return ret;
}
/**
* Pushes an item onto the top of this stack.
* @param item the item to be pushed onto this stack
* @return the <CODE>item</CODE> argument
*/
public Object push(Object item) {
add(item);
return item;
}
/**
* Tests if this stack is empty.
* @return <CODE>true</CODE> if and only if this stack contains no items; <CODE>false</CODE> otherwise
*/
public boolean empty() {
return size() == 0;
}
}
/**
* A class for some basic SOM processing.
*/
public static class Xml2Som {
/**
* The order the names appear in the XML, depth first.
*/
protected ArrayList order;
/**
* The mapping of full names to nodes.
*/
protected HashMap name2Node;
/**
* The data to do a search from the bottom hierarchie.
*/
protected HashMap inverseSearch;
/**
* A stack to be used when parsing.
*/
protected Stack2 stack;
/**
* A temporary store for the repetition count.
*/
protected int anform;
/**
* Escapes a SOM string fragment replacing "." with "\.".
* @param s the unescaped string
* @return the escaped string
*/
public static String escapeSom(String s) {
int idx = s.indexOf('.');
if (idx < 0)
return s;
StringBuffer sb = new StringBuffer();
int last = 0;
while (idx >= 0) {
sb.append(s.substring(last, idx));
sb.append('\\');
last = idx;
idx = s.indexOf('.', idx + 1);
}
sb.append(s.substring(last));
return sb.toString();
}
/**
* Unescapes a SOM string fragment replacing "\." with ".".
* @param s the escaped string
* @return the unescaped string
*/
public static String unescapeSom(String s) {
int idx = s.indexOf('\\');
if (idx < 0)
return s;
StringBuffer sb = new StringBuffer();
int last = 0;
while (idx >= 0) {
sb.append(s.substring(last, idx));
last = idx + 1;
idx = s.indexOf('\\', idx + 1);
}
sb.append(s.substring(last));
return sb.toString();
}
/**
* Outputs the stack as the sequence of elements separated
* by '.'.
* @return the stack as the sequence of elements separated by '.'
*/
protected String printStack() {
if (stack.empty())
return "";
StringBuffer s = new StringBuffer();
for (int k = 0; k < stack.size(); ++k)
s.append('.').append((String)stack.get(k));
return s.substring(1);
}
/**
* Gets the name with the <CODE>#subform</CODE> removed.
* @param s the long name
* @return the short name
*/
public static String getShortName(String s) {
int idx = s.indexOf(".#subform[");
if (idx < 0)
return s;
int last = 0;
StringBuffer sb = new StringBuffer();
while (idx >= 0) {
sb.append(s.substring(last, idx));
idx = s.indexOf("]", idx + 10);
if (idx < 0)
return sb.toString();
last = idx + 1;
idx = s.indexOf(".#subform[", last);
}
sb.append(s.substring(last));
return sb.toString();
}
/**
* Adds a SOM name to the search node chain.
* @param unstack the SOM name
*/
public void inverseSearchAdd(String unstack) {
inverseSearchAdd(inverseSearch, stack, unstack);
}
/**
* Adds a SOM name to the search node chain.
* @param inverseSearch the start point
* @param stack the stack with the separeted SOM parts
* @param unstack the full name
*/
public static void inverseSearchAdd(HashMap inverseSearch, Stack2 stack, String unstack) {
String last = (String)stack.peek();
InverseStore store = (InverseStore)inverseSearch.get(last);
if (store == null) {
store = new InverseStore();
inverseSearch.put(last, store);
}
for (int k = stack.size() - 2; k >= 0; --k) {
last = (String)stack.get(k);
InverseStore store2;
int idx = store.part.indexOf(last);
if (idx < 0) {
store.part.add(last);
store2 = new InverseStore();
store.follow.add(store2);
}
else
store2 = (InverseStore)store.follow.get(idx);
store = store2;
}
store.part.add("");
store.follow.add(unstack);
}
/**
* Searchs the SOM hiearchie from the bottom.
* @param parts the SOM parts
* @return the full name or <CODE>null</CODE> if not found
*/
public String inverseSearchGlobal(ArrayList parts) {
if (parts.isEmpty())
return null;
InverseStore store = (InverseStore)inverseSearch.get(parts.get(parts.size() - 1));
if (store == null)
return null;
for (int k = parts.size() - 2; k >= 0; --k) {
String part = (String)parts.get(k);
int idx = store.part.indexOf(part);
if (idx < 0) {
if (store.isSimilar(part))
return null;
return store.getDefaultName();
}
store = (InverseStore)store.follow.get(idx);
}
return store.getDefaultName();
}
/**
* Splits a SOM name in the individual parts.
* @param name the full SOM name
* @return the split name
*/
public static Stack2 splitParts(String name) {
while (name.startsWith("."))
name = name.substring(1);
Stack2 parts = new Stack2();
int last = 0;
int pos = 0;
String part;
while (true) {
pos = last;
while (true) {
pos = name.indexOf('.', pos);
if (pos < 0)
break;
if (name.charAt(pos - 1) == '\\')
++pos;
else
break;
}
if (pos < 0)
break;
part = name.substring(last, pos);
if (!part.endsWith("]"))
part += "[0]";
parts.add(part);
last = pos + 1;
}
part = name.substring(last);
if (!part.endsWith("]"))
part += "[0]";
parts.add(part);
return parts;
}
/**
* Gets the order the names appear in the XML, depth first.
* @return the order the names appear in the XML, depth first
*/
public ArrayList getOrder() {
return order;
}
/**
* Sets the order the names appear in the XML, depth first
* @param order the order the names appear in the XML, depth first
*/
public void setOrder(ArrayList order) {
this.order = order;
}
/**
* Gets the mapping of full names to nodes.
* @return the mapping of full names to nodes
*/
public HashMap getName2Node() {
return name2Node;
}
/**
* Sets the mapping of full names to nodes.
* @param name2Node the mapping of full names to nodes
*/
public void setName2Node(HashMap name2Node) {
this.name2Node = name2Node;
}
/**
* Gets the data to do a search from the bottom hierarchie.
* @return the data to do a search from the bottom hierarchie
*/
public HashMap getInverseSearch() {
return inverseSearch;
}
/**
* Sets the data to do a search from the bottom hierarchie.
* @param inverseSearch the data to do a search from the bottom hierarchie
*/
public void setInverseSearch(HashMap inverseSearch) {
this.inverseSearch = inverseSearch;
}
}
/**
* Processes the datasets section in the XFA form.
*/
public static class Xml2SomDatasets extends Xml2Som {
/**
* Creates a new instance from the datasets node. This expects
* not the datasets but the data node that comes below.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -