package center.app.common;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import ru.vassaev.core.XMLPath;
import ru.vassaev.core.base.Null;
import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.io.OutputByteBuffer;
import ru.vassaev.core.thread.Process;
import ru.vassaev.core.util.Strings;
import ru.vassaev.core.xml.XMLFileWaiter;
import center.task.AProcessor;
import center.task.Context;
import center.task.Record;
import center.task.State;
import center.task.TaskException;
/**
* Процессор обработки XML, используя SAX
*
* @author Vassaev A.V.
* @version 1.1
*/
public class ForXMLProcessor extends AProcessor {
private Process prc;
private int rown = 0;
private class SAXHandler extends DefaultHandler {
private final XMLPath currPath = new XMLPath();
private Element currElement = null;
private XMLPath relative = new XMLPath();
private final Context cntx;
private final Document doc;
private final Record record;
public SAXHandler(Context cntx) {
super();
doc = XMLFileWaiter.getDocument();
this.cntx = cntx;
this.record = new Record();
prc.regResourceName(record, "all_objects");
}
public void startDocument() {
if (logging) System.out.println("Start document");
}
public void endDocument() {
if (logging) System.out.println("End document");
}
public void startElement(String uri, String name,
String qName, Attributes atts) {
// Если элемент по циклу задан
if (currElement != null) {
// Создать пустой элемент
Element e = doc.createElement(qName);
// Скопировать атрибуты
for (int i = atts.getLength() - 1; i >= 0; i--) {
e.setAttribute(atts.getQName(i), atts.getValue(i));
}
// добавить как дочерний
currElement.appendChild(e);
// относительный путь к выбранному элементу
relative.add(qName);
// новый текущий элемент
currElement = e;
return;
}
// Если элемент по циклу не задан
if (!"".equals(uri)) {
if (logging) System.out.println("Start element: {" + uri + "}" + name);
} else {
if (logging) System.out.println("Start element: " + qName);
}
// Текущий абсолютный путь
currPath.add(qName);
prc.regResourceName(currPath, "row@path");
// Создать элемент
Element e = doc.createElement(name);
// Скопировать аттрибуты
for (int i = atts.getLength() - 1; i >= 0; i--) {
e.setAttribute(atts.getQName(i), atts.getValue(i));
}
// Зарегистрировать объект
prc.regResourceName(e, "row@object");
prc.regResourceName(rown, "row@row");
// Получить результат работы фильтра
String b;
try {
b = cntx.getPrmNvl("filterBefore", "NONE");
} catch (SysException e1) {
e1.printStackTrace();
return;
}
if ("ATTR".equals(b)) {
record.setObject(currPath.toString(), e);
try {
cntx.getPrmByFullName("update");
} catch (SysException ex) {
throw new RuntimeException(ex);
}
rown++;
return;
}
if ("BODY".equals(b)) {
record.setObject(currPath.toString(), e);
currElement = e;
rown++;
return;
}
}
public void endElement(String uri, String name, String qName) {
if ("".equals(uri)) {
if (logging) System.out.println("End element: " + qName);
} else {
if (logging) System.out.println("End element: {" + uri + "}" + name);
}
if (currElement == null) {
currPath.remove(currPath.size() - 1);
return;
}
Node x = currElement.getParentNode();
if (x != null) {
currElement = (Element)x;
relative.remove(relative.size() - 1);
} else {
try {
cntx.getPrmByFullName("update");
} catch (SysException e) {
throw new RuntimeException(e);
} finally {
relative.clear();
currElement = null;
currPath.remove(currPath.size() - 1);
}
}
}
public void characters(char ch[], int start, int length) {
if (currElement != null) {
String val = new String(ch, start, length);
if (logging) System.out.println("String: " + val);
Text txt = doc.createTextNode(val);
currElement.appendChild(txt);
}
if (logging) System.out.print("Characters: \"");
for (int i = start; i < start + length; i++) {
switch (ch[i]) {
case '\\':
if (logging) System.out.print("\\\\");
break;
case '"':
if (logging) System.out.print("\\\"");
break;
case '\n':
if (logging) System.out.print("\\n");
break;
case '\r':
if (logging) System.out.print("\\r");
break;
case '\t':
if (logging) System.out.print("\\t");
break;
default:
if (logging) System.out.print(ch[i]);
break;
}
}
if (logging) System.out.print("\"\n");
}
}
private Object file;
private boolean logging;
public State paramsValidateAndPrepare(Context cntx) throws SysException {
file = cntx.getPrmByFullName("file");
if (Null.equ(file)) {
System.out.println("WARNING: Parameter \"file\" isn't set");
return State.DONE_OK;
}
logging = cntx.getPrmNvl("xml-parsing-log", false);
return null;
}
public State process(Context cntx) throws TaskException, SysException, InterruptedException {
State st = paramsValidateAndPrepare(cntx);
if (st != null)
return st;
File x;
InputStream r = null;
if (file instanceof File)
x = (File)file;
else if (file instanceof OutputByteBuffer) {
x = null;
r = ((OutputByteBuffer) file).getIS();
} else
x = new File(Strings.getString(file));
prc = Process.currentProcess();
if (x != null)
prc.regResourceName(x.getName(), "FN");
try {
XMLReader xr = XMLReaderFactory.createXMLReader();
SAXHandler handler = new SAXHandler(cntx);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
if (x != null) {
if (x.exists())
r = new FileInputStream(x.getCanonicalPath());
else r = null;
}
if (r != null)
try {
xr.parse(new InputSource(r));
} finally {
r.close();
}
} catch (FileNotFoundException e) {
throw new TaskException(State.DONE_ERR, e);
} catch (IOException e) {
throw new TaskException(State.DONE_ERR, e);
} catch (SAXException e) {
throw new TaskException(State.DONE_ERR, e);
} finally {
prc.regResourceName(rown, "row@count");
}
String rename = cntx.getPrmString("rename");
if (x!=null && rename != null) {
x.renameTo(new File(rename));
}
return State.DONE_OK;
}
public Set<String> dependentOn() {
// TODO Auto-generated method stub
return null;
}
public Set<String> loopDependentOn() {
// TODO Auto-generated method stub
return null;
}
}