blob: b3fd66611ab764fab8fb5bcf8d350b3e0fdbecc5 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.store;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlDocumentProperties;
import org.apache.xmlbeans.XmlOptions;
import org.w3c.dom.Node;
import javax.xml.namespace.QName;
import java.util.ArrayList;
final class DomSaver extends Saver {
private Cur _nodeCur;
private SchemaType _type;
private final SchemaTypeLoader _stl;
private final XmlOptions _options;
private final boolean _isFrag;
DomSaver(Cur c, boolean isFrag, XmlOptions options) {
super(c, options);
if (c.isUserNode()) {
_type = c.getUser().get_schema_type();
}
_stl = c._locale._schemaTypeLoader;
_options = options;
_isFrag = isFrag;
}
Node saveDom() {
Locale l = Locale.getLocale(_stl, _options);
l.enter();
try {
_nodeCur = l.getCur(); // Not weak or temp
// Build the tree
//noinspection StatementWithEmptyBody
while (process());
// Set the type
while (!_nodeCur.isRoot()) {
_nodeCur.toParent();
}
if (_type != null) {
_nodeCur.setType(_type);
}
Node node = (Node) _nodeCur.getDom();
_nodeCur.release();
_nodeCur = null;
return node;
} finally {
l.exit();
}
}
protected boolean emitElement(SaveCur c, ArrayList attrNames, ArrayList attrValues) {
// If there was text or comments before the frag element, I will loose them -- oh well
// Also, I will lose any attributes and namesapces on the fragment -- DOM can
// have attrs in fragments
if (Locale.isFragmentQName(c.getName())) {
_nodeCur.moveTo(null, Cur.NO_POS);
}
ensureDoc();
_nodeCur.createElement(getQualifiedName(c, c.getName()));
_nodeCur.next();
for (iterateMappings(); hasMapping(); nextMapping()) {
_nodeCur.createAttr(_nodeCur._locale.createXmlns(mappingPrefix()));
_nodeCur.next();
_nodeCur.insertString(mappingUri());
_nodeCur.toParent();
_nodeCur.skipWithAttrs();
}
for (int i = 0; i < attrNames.size(); i++) {
_nodeCur.createAttr(getQualifiedName(c, (QName) attrNames.get(i)));
_nodeCur.next();
_nodeCur.insertString((String) attrValues.get(i));
_nodeCur.toParent();
_nodeCur.skipWithAttrs();
}
return false;
}
protected void emitFinish(SaveCur c) {
if (!Locale.isFragmentQName(c.getName())) {
assert _nodeCur.isEnd();
_nodeCur.next();
}
}
protected void emitText(SaveCur c) {
ensureDoc();
Object src = c.getChars();
if (c._cchSrc > 0) {
_nodeCur.insertChars(src, c._offSrc, c._cchSrc);
_nodeCur.next();
}
}
protected void emitComment(SaveCur c) {
ensureDoc();
_nodeCur.createComment();
emitTextValue(c);
_nodeCur.skip();
}
protected void emitProcinst(SaveCur c) {
ensureDoc();
_nodeCur.createProcinst(c.getName().getLocalPart());
emitTextValue(c);
_nodeCur.skip();
}
protected void emitDocType(String docTypeName, String publicId, String systemId) {
ensureDoc();
XmlDocumentProperties props = Locale.getDocProps(_nodeCur, true);
props.setDoctypeName(docTypeName);
props.setDoctypePublicId(publicId);
props.setDoctypeSystemId(systemId);
}
protected void emitStartDoc(SaveCur c) {
ensureDoc();
}
protected void emitEndDoc(SaveCur c) {
}
private QName getQualifiedName(SaveCur c, QName name) {
String uri = name.getNamespaceURI();
String prefix = uri.length() > 0 ? getUriMapping(uri) : "";
if (prefix.equals(name.getPrefix())) {
return name;
}
return _nodeCur._locale.makeQName(uri, name.getLocalPart(), prefix);
}
private void emitTextValue(SaveCur c) {
c.push();
c.next();
if (c.isText()) {
_nodeCur.next();
_nodeCur.insertChars(c.getChars(), c._offSrc, c._cchSrc);
_nodeCur.toParent();
}
c.pop();
}
private void ensureDoc() {
if (!_nodeCur.isPositioned()) {
if (_isFrag) {
_nodeCur.createDomDocFragRoot();
} else {
_nodeCur.createDomDocumentRoot();
}
_nodeCur.next();
}
}
}