/******************************************************************************* * Copyright (c) 2001, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Jens Lukowski/Innoopract - initial renaming/restructuring * David Carver (STAR) - bug 296999 - Inefficient use of new String() * Angelo Zerr <angelo.zerr@gmail.com> - copied from org.eclipse.wst.xml.core.internal.document.XMLModelUpdater * modified in order to process JSON Objects. *******************************************************************************/ package org.eclipse.wst.json.core.internal.document; import java.util.Enumeration; import java.util.Iterator; import org.eclipse.wst.json.core.document.IJSONNode; import org.eclipse.wst.json.core.document.IJSONObject; import org.eclipse.wst.json.core.regions.JSONRegionContexts; import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; /** * JSONModelUpdater class */ public class JSONModelUpdater { private int diff = 0; private int gapLength = 0; private int gapOffset = 0; private IStructuredDocumentRegion gapStructuredDocumentRegion = null; private ISourceGenerator generator = null; private JSONModelImpl model = null; private JSONNodeImpl nextNode = null; private JSONNodeImpl parentNode = null; protected JSONModelUpdater(JSONModelImpl model) { super(); if (model != null) { this.model = model; this.generator = model.getGenerator(); } } /** * changeAttrValue method * * @param attrNode * org.w3c.dom.Attr */ // private void changeAttrName(Attr attrNode) { // if (attrNode == null) // return; // // AttrImpl attr = (AttrImpl) attrNode; // IJSONObject element = (IJSONObject) attr.getOwnerIJSONObject(); // if (element == null) // return; // // if (element.isCommentTag()) { // changeStartTag(element); // return; // } // // int offset = element.getStartOffset(); // int start = offset; // int end = offset; // // String name = attr.getName(); // if (name == null) // name = JSONNodeImpl.EMPTY_STRING; // ITextRegion nameRegion = attr.getNameRegion(); // if (nameRegion == null) // return; // error // start += nameRegion.getStart(); // // use getTextEnd() because getEnd() may include the tailing spaces // end += nameRegion.getTextEnd(); // // replaceSource(name, start, end); // } /** * changeAttrValue method * * @param attrNode * org.w3c.dom.Attr */ // private void changeAttrValue(Attr attrNode) { // if (attrNode == null) // return; // // AttrImpl attr = (AttrImpl) attrNode; // IJSONObject element = (IJSONObject) attr.getOwnerIJSONObject(); // if (element == null) // return; // // if (element.isCommentTag()) { // changeStartTag(element); // return; // } // // int offset = element.getStartOffset(); // int start = offset; // int end = offset; // // String value = null; // ITextRegion valueRegion = attr.getValueRegion(); // if (valueRegion != null) { // char quote = 0; // no quote preference // // DW: 4/16/2003 due to change in structuredDocument ... we need a // // flatnode to // // get at region values. For now I'll assume this is always the // // first // // flatnode .. may need to make smarter later (e.g. to search for // // the flatnode that this.valueRegion belongs to. // IStructuredDocumentRegion documentRegion = element // .getFirstStructuredDocumentRegion(); // String oldValue = documentRegion.getText(valueRegion); // if (oldValue != null && oldValue.length() > 0) { // char firstChar = oldValue.charAt(0); // if (firstChar == '"' || firstChar == '\'') { // quote = firstChar; // } // } // // ITextRegion startRegion = valueRegion; // // value = this.generator.generateAttrValue(attr, quote); // if (value == null) { // value = JSONNodeImpl.EMPTY_STRING; // // remove equal too // ITextRegion equalRegion = attr.getEqualRegion(); // if (equalRegion != null) // startRegion = equalRegion; // } // attr.setValueRegion(valueRegion); // reset value // // start += startRegion.getStart(); // // use getTextEnd() because getEnd() may include the tailing // // spaces // end += valueRegion.getTextEnd(); // } else { // ITextRegion equalRegion = attr.getEqualRegion(); // // value = this.generator.generateAttrValue(attr); // if (value == null) { // if (equalRegion == null) // return; // nothng to do // value = JSONNodeImpl.EMPTY_STRING; // // remove equal // start += equalRegion.getStart(); // end += equalRegion.getTextEnd(); // } else { // if (equalRegion != null) { // // use getTextEnd() because getEnd() may include the // // tailing spaces // start += equalRegion.getTextEnd(); // } else { // ITextRegion nameRegion = attr.getNameRegion(); // if (nameRegion == null) // return; // must never happen // // use getTextEnd() because getEnd() may include the // // tailing spaces // start += nameRegion.getTextEnd(); // value = '=' + value; // } // end = start; // } // } // // replaceSource(value, start, end); // } /** */ // void changeEndTag(IJSONObject element) { // String source = this.generator.generateEndTag(element); // if (source == null) // return; // int length = source.length(); // if (length == 0) // return; // // IJSONObject impl = (IJSONObject) element; // int offset = impl.getEndStartOffset(); // int start = offset; // int end = offset; // if (impl.hasEndTag()) { // end = impl.getEndOffset(); // this.gapStructuredDocumentRegion = impl // .getEndStructuredDocumentRegion(); // impl.setEndStructuredDocumentRegion(new StructuredDocumentRegionProxy( // offset, length)); // } // // replaceSource(source, start, end); // } /** * changeName method * * @param node * org.w3c.dom.Node */ // void changeName(Node node) { // if (node == null) // return; // if (getStructuredDocument() == null) // return; // // // support changing name of attribute for setPrefix() // short nodeType = node.getNodeType(); // if (nodeType == Node.ATTRIBUTE_NODE) { // changeAttrName((Attr) node); // return; // } // // // not supported // return; // } void changeRegion(RegionChangedEvent change, IStructuredDocumentRegion flatNode, ITextRegion region) { if (change.getOffset() >= flatNode.getStartOffset() + region.getTextEnd()) { // change is entirely in white-space return; } JSONNodeImpl root = (JSONNodeImpl) this.model.getDocument(); this.parentNode = root; this.nextNode = (JSONNodeImpl) root.getFirstChild(); removeGapStructuredDocumentRegion(flatNode); insertGapStructuredDocumentRegionBefore(flatNode.getStart()); changeStructuredDocumentRegion(flatNode); insertGapStructuredDocumentRegionAfter(flatNode.getEnd()); } /** * This is a fallback method to regenerate the start tag. */ void changeStartTag(IJSONObject element) { if (element == null) return; JSONObjectImpl impl = (JSONObjectImpl) element; if (!impl.hasStartTag() && !impl.hasEndTag()) { // need to generate the start and the end tags IJSONNode parent = element.getParentNode(); if (parent != null) { replaceChild(parent, element, element); return; } // else error } String source = this.generator.generateStartTag(element); if (source == null) return; int length = source.length(); if (length == 0) return; int offset = impl.getStartOffset(); int start = offset; int end = offset; if (impl.hasStartTag()) { end = impl.getStartEndOffset(); this.gapStructuredDocumentRegion = impl .getStartStructuredDocumentRegion(); } impl.setStartStructuredDocumentRegion(new StructuredDocumentRegionProxy( offset, length)); replaceSource(source, start, end); } private void changeStructuredDocumentRegion( IStructuredDocumentRegion oldStructuredDocumentRegion) { if (oldStructuredDocumentRegion == null) return; // error if (this.parentNode == null) return; // error int oldOffset = oldStructuredDocumentRegion.getStart(); int oldEnd = oldStructuredDocumentRegion.getEnd(); boolean isEndTag = false; // find owner node JSONNodeImpl ownerNode = null; while (this.parentNode != null) { if (this.nextNode != null) { IStructuredDocumentRegion nextStructuredDocumentRegion = this.nextNode .getStructuredDocumentRegion(); if (nextStructuredDocumentRegion != null) { if (nextStructuredDocumentRegion == oldStructuredDocumentRegion) { ownerNode = this.nextNode; break; } int nextOffset = nextStructuredDocumentRegion.getStart(); if (nextOffset == oldOffset) { // found ownerNode = this.nextNode; break; } // if (this.nextNode.getNodeType() == Node.TEXT_NODE) { // TextImpl text = (TextImpl) this.nextNode; // if (text.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) { // ownerNode = this.nextNode; // break; // } // int nextEnd = nextStructuredDocumentRegion.getEnd(); // if (nextOffset < oldEnd && nextEnd > oldOffset) { // ownerNode = this.nextNode; // break; // } // } } IJSONNode child = this.nextNode.getFirstChild(); if (child != null) { this.parentNode = this.nextNode; this.nextNode = (JSONNodeImpl) child; continue; } if (this.nextNode.getNodeType() == IJSONNode.OBJECT_NODE) { this.parentNode = this.nextNode; this.nextNode = null; continue; } this.nextNode = (JSONNodeImpl) this.nextNode.getNextSibling(); if (this.nextNode != null) continue; } if (this.parentNode.getNodeType() == IJSONNode.OBJECT_NODE) { IJSONObject element = (IJSONObject) this.parentNode; IStructuredDocumentRegion endStructuredDocumentRegion = element .getEndStructuredDocumentRegion(); if (endStructuredDocumentRegion != null) { if (endStructuredDocumentRegion == oldStructuredDocumentRegion) { ownerNode = this.parentNode; isEndTag = true; break; } int endOffset = endStructuredDocumentRegion.getStart(); if (endOffset == oldOffset) { // found ownerNode = this.parentNode; isEndTag = true; break; } } } this.nextNode = (JSONNodeImpl) this.parentNode.getNextSibling(); this.parentNode = (JSONNodeImpl) this.parentNode.getParentNode(); } if (ownerNode == null) throw new StructuredDocumentRegionManagementException(); short nodeType = ownerNode.getNodeType(); if (nodeType == IJSONNode.OBJECT_NODE) { JSONObjectImpl element = (JSONObjectImpl) ownerNode; if (isEndTag) { element.setEndStructuredDocumentRegion(oldStructuredDocumentRegion); } else { element.setStartStructuredDocumentRegion(oldStructuredDocumentRegion); updateAttrRegions(element, oldStructuredDocumentRegion); } } else /*if (nodeType == Node.TEXT_NODE) { TextImpl text = (TextImpl) ownerNode; IStructuredDocumentRegion flatNode = text .getStructuredDocumentRegion(); if (flatNode == oldStructuredDocumentRegion) { int newOffset = oldOffset; int newEnd = oldEnd; if (oldOffset == this.gapOffset) { newOffset += this.diff; } else { newEnd = this.gapOffset; } int newLength = newEnd - newOffset; IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy( newOffset, newLength, oldStructuredDocumentRegion); text.setStructuredDocumentRegion(newStructuredDocumentRegion); if (oldEnd > newEnd) { this.nextNode = (JSONNodeImpl) text.getNextSibling(); changeStructuredDocumentRegion(oldStructuredDocumentRegion); } return; } if (flatNode instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode; int offset = proxy.getOffset(); int end = offset + proxy.getLength(); if (proxy.getStructuredDocumentRegion() == null) { if (offset == oldOffset && end == oldEnd) { text.setStructuredDocumentRegion(oldStructuredDocumentRegion); } else { if (end > oldEnd) { StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer(); container .appendStructuredDocumentRegion(oldStructuredDocumentRegion); proxy.setOffset(oldEnd); proxy.setLength(end - oldEnd); container.appendStructuredDocumentRegion(proxy); text.setStructuredDocumentRegion(container); } else { proxy.setStructuredDocumentRegion(oldStructuredDocumentRegion); if (end < oldEnd) { // to be shared this.nextNode = (JSONNodeImpl) text .getNextSibling(); changeStructuredDocumentRegion(oldStructuredDocumentRegion); } } } return; } if (offset >= this.gapOffset) { proxy.setOffset(offset + this.diff); end += this.diff; } if (end < oldEnd) { // to be shared this.nextNode = (JSONNodeImpl) text.getNextSibling(); changeStructuredDocumentRegion(oldStructuredDocumentRegion); return; } } else if (flatNode instanceof StructuredDocumentRegionContainer) { StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode; int count = container.getStructuredDocumentRegionCount(); for (int i = 0; i < count; i++) { IStructuredDocumentRegion content = container .getStructuredDocumentRegion(i); if (content == null) continue; // error if (content == oldStructuredDocumentRegion) { int newOffset = oldOffset; int newEnd = oldEnd; if (oldOffset == this.gapOffset) { newOffset += this.diff; } else { newEnd = this.gapOffset; } int newLength = newEnd - newOffset; IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy( newOffset, newLength, oldStructuredDocumentRegion); container.replaceStructuredDocumentRegion( newStructuredDocumentRegion, i); if (oldEnd > newEnd) { // to be shared this.nextNode = (JSONNodeImpl) text.getNextSibling(); changeStructuredDocumentRegion(oldStructuredDocumentRegion); } return; } if (content instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content; int offset = proxy.getOffset(); int end = offset + proxy.getLength(); if (end <= oldOffset) continue; if (proxy.getStructuredDocumentRegion() == null) { if (offset == oldOffset && end == oldEnd) { container.replaceStructuredDocumentRegion( oldStructuredDocumentRegion, i); } else { if (end > oldEnd) { container.insertStructuredDocumentRegion( oldStructuredDocumentRegion, i); proxy.setOffset(oldEnd); proxy.setLength(end - oldEnd); } else { proxy.setStructuredDocumentRegion(oldStructuredDocumentRegion); if (end < oldEnd) { // to be shared this.nextNode = (JSONNodeImpl) text .getNextSibling(); changeStructuredDocumentRegion(oldStructuredDocumentRegion); } } } return; } if (offset >= this.gapOffset) { proxy.setOffset(offset + this.diff); end += this.diff; } if (end < oldEnd) { // to be shared this.nextNode = (JSONNodeImpl) text.getNextSibling(); changeStructuredDocumentRegion(oldStructuredDocumentRegion); return; } } } } else { throw new StructuredDocumentRegionManagementException(); } } else {*/ ownerNode.setStructuredDocumentRegion(oldStructuredDocumentRegion); //} } /** */ // private void changeTextData(Text text) { // if (text == null) // return; // // String source = this.generator.generateSource(text); // if (source == null) // source = JSONNodeImpl.EMPTY_STRING; // int length = source.length(); // // TextImpl impl = (TextImpl) text; // int start = impl.getStartOffset(); // int end = impl.getEndOffset(); // int offset = start; // // // make sure previous tag is closed // Node prev = text.getPreviousSibling(); // if (prev != null) { // String preTag = getCloseTag((IJSONNode) prev); // if (preTag != null && preTag.length() > 0) { // offset += preTag.length(); // source = preTag + source; // } // } else { // Node parent = text.getParentNode(); // if (parent != null && parent.getNodeType() == IJSONNode.OBJECT_NODE) { // IJSONObject element = (IJSONObject) parent; // String preTag = getStartCloseTag(element); // if (preTag != null && preTag.length() > 0) { // offset += preTag.length(); // StringBuffer buffer = new StringBuffer(); // buffer.append(preTag); // buffer.append(source); // if (text.getNextSibling() == null // && !element.hasEndTag() // && (element.isJSPContainer() || element // .isCDATAContainer())) { // // need to generate the end tag // String postTag = this.generator.generateEndTag(element); // if (postTag != null) { // int postLength = postTag.length(); // if (postLength > 0) { // buffer.append(postTag); // int postOffset = offset + length; // IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy( // postOffset, postLength); // element.setEndStructuredDocumentRegion(flatNode); // } // } // } // source = buffer.toString(); // } // } // } // // this.gapStructuredDocumentRegion = impl.getStructuredDocumentRegion(); // IStructuredDocumentRegion newStructuredDocumentRegion = null; // if (length > 0) // newStructuredDocumentRegion = new StructuredDocumentRegionProxy( // offset, length); // impl.setStructuredDocumentRegion(newStructuredDocumentRegion); // // replaceSource(source, start, end); // } /** * changeValue method * * @param node * org.w3c.dom.Node */ void changeValue(IJSONNode node) { if (node == null) return; if (getStructuredDocument() == null) return; short nodeType = node.getNodeType(); // if (nodeType == Node.TEXT_NODE) { // changeTextData((Text) node); // return; // } // if (nodeType == Node.ATTRIBUTE_NODE) { // changeAttrValue((Attr) node); // return; // } if (nodeType == IJSONNode.OBJECT_NODE) { changeStartTag((IJSONObject) node); return; } String source = this.generator.generateSource(node); if (source == null) source = JSONNodeImpl.EMPTY_STRING; int length = source.length(); JSONNodeImpl impl = (JSONNodeImpl) node; int start = impl.getStartOffset(); int end = impl.getEndOffset(); this.gapStructuredDocumentRegion = impl.getStructuredDocumentRegion(); IStructuredDocumentRegion flatNode = null; if (length > 0) flatNode = new StructuredDocumentRegionProxy(start, length); impl.setStructuredDocumentRegion(flatNode); replaceSource(source, start, end); } /** */ // private String getAttrValueClose(IJSONIJSONObject element) { // if (element == null) // return null; // // IStructuredDocumentRegion flatNode = element // .getStartStructuredDocumentRegion(); // if (flatNode == null) // return null; // ITextRegion region = StructuredDocumentRegionUtil // .getLastRegion(flatNode); // if (region == null // || region.getType() != JSONRegionContexts.JSON_TAG_ATTRIBUTE_VALUE) // return null; // String value = flatNode.getText(region); // if (value == null) // return null; // int length = value.length(); // if (length == 0) // return null; // // // check open JSP tag // boolean closeJSPTag = false; // int offset = value.indexOf(JSPTag.TAG_OPEN); // while (offset >= 0) { // offset = value.indexOf(JSPTag.TAG_CLOSE, offset + 2); // if (offset < 0) { // closeJSPTag = true; // break; // } // offset = value.indexOf(JSPTag.TAG_OPEN, offset + 2); // } // // // check quote // boolean closeQuote = false; // char firstChar = value.charAt(0); // if (firstChar == '"' || firstChar == '\'') { // if (closeJSPTag || length == 1 // || value.charAt(length - 1) != firstChar) { // closeQuote = true; // } // } // // if (!closeJSPTag && !closeQuote) // return null; // // StringBuffer buffer = new StringBuffer(); // if (closeJSPTag) // buffer.append(JSPTag.TAG_CLOSE); // if (closeQuote) // buffer.append(firstChar); // return buffer.toString(); // } /** * Gather close tags recursively. */ // private String getCloseTag(IJSONNode node) { // if (node == null || node.isClosed()) // return null; // // if (node.getNodeType() != IJSONNode.OBJECT_NODE) { // return this.generator.generateCloseTag(node); // } // // IJSONObject element = (IJSONObject) node; // if (element.hasEndTag()) { // // end tag is not closed // return this.generator.generateCloseTag(element); // } // // // no end tag // int offset = element.getEndOffset(); // StringBuffer buffer = new StringBuffer(); // // IJSONNode lastChild = (IJSONNode) element.getLastChild(); // if (lastChild == null) { // if (!element.isStartTagClosed()) { // if (element.preferEmptyTag()) // element.setEmptyTag(true); // String closeTag = getStartCloseTag(element); // if (closeTag != null) { // int length = closeTag.length(); // if (length > 0) { // buffer.append(closeTag); // offset += length; // } // } // } // } else { // String closeTag = getCloseTag(lastChild); // if (closeTag != null) { // int length = closeTag.length(); // if (length > 0) { // buffer.append(closeTag); // offset += length; // } // } // } // // String endTag = this.generator.generateEndTag(element); // if (endTag != null) { // int length = endTag.length(); // if (length > 0) { // buffer.append(endTag); // IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy( // offset, length); // element.setEndStructuredDocumentRegion(flatNode); // } // } // // return buffer.toString(); // } // private boolean isSelfClosedContainer(IJSONIJSONObject element) { // if (element.getStartStructuredDocumentRegion() != null) { // final ModelQuery mq = ModelQueryUtil.getModelQuery(element // .getOwnerDocument()); // if (mq != null) { // final CMIJSONObjectDeclaration node = mq // .getCMIJSONObjectDeclaration(element); // if (node != null) { // return node.getContentType() != CMIJSONObjectDeclaration.EMPTY // && element.getStartStructuredDocumentRegion() // .getLastRegion().getType() == JSONRegionContexts.JSON_EMPTY_TAG_CLOSE; // } // } // } // return false; // } /** */ // private String getStartCloseTag(IJSONIJSONObject element) { // if (element == null || element.isStartTagClosed()) // return null; // // StringBuffer buffer = new StringBuffer(); // String attrValueClose = getAttrValueClose(element); // if (attrValueClose != null) // buffer.append(attrValueClose); // String closeTag = this.generator.generateCloseTag(element); // if (closeTag != null) // buffer.append(closeTag); // return buffer.toString(); // } private IStructuredDocument getStructuredDocument() { if (model == null) return null; return model.getStructuredDocument(); } /** */ void initialize() { this.gapStructuredDocumentRegion = null; this.gapOffset = 0; this.gapLength = 0; this.diff = 0; this.parentNode = null; this.nextNode = null; } private void insertGapStructuredDocumentRegionAfter(int endOffset) { if (this.gapStructuredDocumentRegion == null) return; if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion; IStructuredDocumentRegion flatNode = proxy .getStructuredDocumentRegion(); if (flatNode != null) insertStructuredDocumentRegion(flatNode); } else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) { StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion; int count = container.getStructuredDocumentRegionCount(); for (int i = 0; i < count; i++) { IStructuredDocumentRegion content = container .getStructuredDocumentRegion(i); if (content == null) continue; if (content.getStart() < endOffset) continue; if (content instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content; IStructuredDocumentRegion flatNode = proxy .getStructuredDocumentRegion(); if (flatNode != null) insertStructuredDocumentRegion(flatNode); } else { insertStructuredDocumentRegion(content); } } } else { insertStructuredDocumentRegion(this.gapStructuredDocumentRegion); } } private void insertGapStructuredDocumentRegionBefore(int startOffset) { if (this.gapStructuredDocumentRegion == null) return; if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion; IStructuredDocumentRegion flatNode = proxy .getStructuredDocumentRegion(); if (flatNode != null) insertStructuredDocumentRegion(flatNode); } else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) { StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion; int count = container.getStructuredDocumentRegionCount(); for (int i = 0; i < count; i++) { IStructuredDocumentRegion content = container .getStructuredDocumentRegion(i); if (content == null) continue; if (content.getStart() >= startOffset) return; if (content instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content; IStructuredDocumentRegion flatNode = proxy .getStructuredDocumentRegion(); if (flatNode != null) insertStructuredDocumentRegion(flatNode); } else { insertStructuredDocumentRegion(content); } } } else { insertStructuredDocumentRegion(this.gapStructuredDocumentRegion); } } /** */ private void insertStructuredDocumentRegion( IStructuredDocumentRegion newStructuredDocumentRegion) { if (newStructuredDocumentRegion == null) return; // error if (this.parentNode == null) return; // error int newOffset = newStructuredDocumentRegion.getStart(); int newEnd = newStructuredDocumentRegion.getEnd(); boolean isEndTag = false; // find owner node JSONNodeImpl ownerNode = null; while (this.parentNode != null) { if (this.nextNode != null) { IStructuredDocumentRegion nextStructuredDocumentRegion = this.nextNode .getStructuredDocumentRegion(); if (nextStructuredDocumentRegion != null) { int nextOffset = nextStructuredDocumentRegion.getStart(); if (nextOffset == newOffset) { // found ownerNode = this.nextNode; break; } // if (this.nextNode.getNodeType() == Node.TEXT_NODE) { // int nextEnd = nextStructuredDocumentRegion.getEnd(); // if (nextOffset < newEnd && nextEnd > newOffset) { // ownerNode = this.nextNode; // break; // } // } } IJSONNode child = this.nextNode.getFirstChild(); if (child != null) { this.parentNode = this.nextNode; this.nextNode = (JSONNodeImpl) child; continue; } if (this.nextNode.getNodeType() == IJSONNode.OBJECT_NODE) { this.parentNode = this.nextNode; this.nextNode = null; continue; } this.nextNode = (JSONNodeImpl) this.nextNode.getNextSibling(); if (this.nextNode != null) continue; } if (this.parentNode.getNodeType() == IJSONNode.OBJECT_NODE) { IJSONObject element = (IJSONObject) this.parentNode; IStructuredDocumentRegion endStructuredDocumentRegion = element .getEndStructuredDocumentRegion(); if (endStructuredDocumentRegion != null) { int endOffset = endStructuredDocumentRegion.getStart(); if (endOffset == newOffset) { // found ownerNode = this.parentNode; isEndTag = true; break; } } } this.nextNode = (JSONNodeImpl) this.parentNode.getNextSibling(); this.parentNode = (JSONNodeImpl) this.parentNode.getParentNode(); } if (ownerNode == null) throw new StructuredDocumentRegionManagementException(); short nodeType = ownerNode.getNodeType(); if (nodeType == IJSONNode.OBJECT_NODE) { JSONObjectImpl element = (JSONObjectImpl) ownerNode; if (isEndTag) { element.setEndStructuredDocumentRegion(newStructuredDocumentRegion); } else { element.setStartStructuredDocumentRegion(newStructuredDocumentRegion); updateAttrRegions(element, newStructuredDocumentRegion); } } else // if (nodeType == Node.TEXT_NODE) { // TextImpl text = (TextImpl) ownerNode; // IStructuredDocumentRegion oldStructuredDocumentRegion = text // .getStructuredDocumentRegion(); // if (oldStructuredDocumentRegion == null) { // throw new StructuredDocumentRegionManagementException(); // } // int oldOffset = oldStructuredDocumentRegion.getStart(); // int oldEnd = oldStructuredDocumentRegion.getEnd(); // if (oldOffset == newOffset && oldEnd == newEnd) { // text.setStructuredDocumentRegion(newStructuredDocumentRegion); // return; // } // // if (oldStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) { // StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) oldStructuredDocumentRegion; // if (oldEnd > newEnd) { // StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer(); // if (oldOffset == newOffset) { // container // .appendStructuredDocumentRegion(newStructuredDocumentRegion); // } else { // StructuredDocumentRegionProxy newProxy = new StructuredDocumentRegionProxy(); // newProxy.setOffset(oldOffset); // newProxy.setLength(newEnd - oldOffset); // newProxy.setStructuredDocumentRegion(newStructuredDocumentRegion); // container.appendStructuredDocumentRegion(newProxy); // } // proxy.setOffset(newEnd); // proxy.setLength(oldEnd - newEnd); // container.appendStructuredDocumentRegion(proxy); // text.setStructuredDocumentRegion(container); // } else { // proxy.setStructuredDocumentRegion(newStructuredDocumentRegion); // // if (oldEnd < newEnd) { // to be shared // this.nextNode = (JSONNodeImpl) text.getNextSibling(); // insertStructuredDocumentRegion(newStructuredDocumentRegion); // } // } // return; // } // // if (oldStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) { // StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) oldStructuredDocumentRegion; // int count = container.getStructuredDocumentRegionCount(); // for (int i = 0; i < count; i++) { // IStructuredDocumentRegion content = container // .getStructuredDocumentRegion(i); // if (content == null) // continue; // error // int offset = content.getStart(); // int end = content.getEnd(); // if (end <= newOffset) // continue; // if (offset == newOffset && end == newEnd) { // container.replaceStructuredDocumentRegion( // newStructuredDocumentRegion, i); // return; // } // // if (content instanceof StructuredDocumentRegionProxy) { // StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content; // if (end > newEnd) { // if (offset == newOffset) { // container.insertStructuredDocumentRegion( // newStructuredDocumentRegion, i); // } else { // StructuredDocumentRegionProxy newProxy = new StructuredDocumentRegionProxy(); // newProxy.setOffset(offset); // newProxy.setLength(newEnd - offset); // newProxy.setStructuredDocumentRegion(newStructuredDocumentRegion); // container.insertStructuredDocumentRegion( // newProxy, i); // } // proxy.setOffset(newEnd); // proxy.setLength(end - newEnd); // return; // } else { // proxy.setStructuredDocumentRegion(newStructuredDocumentRegion); // if (end == newEnd) // return; // } // } // } // // if (oldEnd < newEnd) { // to be shared // this.nextNode = (JSONNodeImpl) text.getNextSibling(); // insertStructuredDocumentRegion(newStructuredDocumentRegion); // } // return; // } else { // throw new StructuredDocumentRegionManagementException(); // } // } else { ownerNode.setStructuredDocumentRegion(newStructuredDocumentRegion); //} } private void removeGapStructuredDocumentRegion( IStructuredDocumentRegion oldStructuredDocumentRegion) { if (this.gapStructuredDocumentRegion == null) return; if (this.gapStructuredDocumentRegion == oldStructuredDocumentRegion) { this.gapStructuredDocumentRegion = null; return; } if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion; IStructuredDocumentRegion flatNode = proxy .getStructuredDocumentRegion(); if (flatNode == oldStructuredDocumentRegion) this.gapStructuredDocumentRegion = null; } else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) { StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion; int count = container.getStructuredDocumentRegionCount(); for (int i = 0; i < count; i++) { IStructuredDocumentRegion content = container .getStructuredDocumentRegion(i); if (content == null) continue; if (content == oldStructuredDocumentRegion) { if (count > 1) container.removeStructuredDocumentRegion(i); else this.gapStructuredDocumentRegion = null; return; } if (content instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content; if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) { if (count > 1) container.removeStructuredDocumentRegion(i); else this.gapStructuredDocumentRegion = null; return; } } } } } private void removeStructuredDocumentRegion( IStructuredDocumentRegion oldStructuredDocumentRegion) { if (oldStructuredDocumentRegion == null) return; // error if (this.parentNode == null) return; // error int gapEnd = this.gapOffset + this.gapLength; int oldOffset = oldStructuredDocumentRegion.getStart(); int oldEnd = oldStructuredDocumentRegion.getEnd(); if (oldOffset >= this.gapOffset && oldEnd <= gapEnd) return; // do nothing int oldLength = oldEnd - oldOffset; if (oldOffset >= gapEnd) oldOffset += this.diff; // find owner node JSONNodeImpl ownerNode = null; JSONObjectImpl ownerEndTag = null; //TextImpl ownerText = null; while (this.parentNode != null) { if (this.nextNode != null) { if (this.nextNode.getStructuredDocumentRegion() == oldStructuredDocumentRegion) { ownerNode = this.nextNode; break; } // if (this.nextNode.getNodeType() == Node.TEXT_NODE) { // TextImpl text = (TextImpl) this.nextNode; // if (text.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) { // ownerNode = this.nextNode; // ownerText = text; // break; // } // } IJSONNode child = this.nextNode.getFirstChild(); if (child != null) { this.parentNode = this.nextNode; this.nextNode = (JSONNodeImpl) child; continue; } if (this.nextNode.getNodeType() == IJSONNode.OBJECT_NODE) { this.parentNode = this.nextNode; this.nextNode = null; continue; } this.nextNode = (JSONNodeImpl) this.nextNode.getNextSibling(); if (this.nextNode != null) continue; } if (this.parentNode.getNodeType() == IJSONNode.OBJECT_NODE) { JSONObjectImpl element = (JSONObjectImpl) this.parentNode; if (element.getEndStructuredDocumentRegion() == oldStructuredDocumentRegion) { ownerNode = this.parentNode; ownerEndTag = element; break; } } this.nextNode = (JSONNodeImpl) this.parentNode.getNextSibling(); this.parentNode = (JSONNodeImpl) this.parentNode.getParentNode(); } if (ownerNode == null) throw new StructuredDocumentRegionManagementException(); /*if (ownerText != null) { IStructuredDocumentRegion flatNode = ownerText .getStructuredDocumentRegion(); if (flatNode == oldStructuredDocumentRegion) { IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy( oldOffset, oldLength); ownerText .setStructuredDocumentRegion(newStructuredDocumentRegion); return; } if (flatNode instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode; if (proxy.getStructuredDocumentRegion() != oldStructuredDocumentRegion) { throw new StructuredDocumentRegionManagementException(); } int offset = proxy.getOffset(); int end = offset + proxy.getLength(); if (offset >= this.gapOffset) { proxy.setOffset(offset + this.diff); } proxy.setStructuredDocumentRegion(null); if (end < oldEnd && (end < this.gapOffset || oldEnd > gapEnd)) { // has // shared removeStructuredDocumentRegion(oldStructuredDocumentRegion); return; } } else if (flatNode instanceof StructuredDocumentRegionContainer) { StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode; int count = container.getStructuredDocumentRegionCount(); for (int i = 0; i < count; i++) { IStructuredDocumentRegion content = container .getStructuredDocumentRegion(i); if (content == null) continue; // error if (content == oldStructuredDocumentRegion) { IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy( oldOffset, oldLength); container.replaceStructuredDocumentRegion( newStructuredDocumentRegion, i); return; } if (content instanceof StructuredDocumentRegionProxy) { StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content; if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) { int offset = proxy.getOffset(); int end = offset + proxy.getLength(); if (offset >= this.gapOffset) { proxy.setOffset(offset + this.diff); } proxy.setStructuredDocumentRegion(null); if (end < oldEnd && (end < this.gapOffset || oldEnd > gapEnd)) { // has // shared removeStructuredDocumentRegion(oldStructuredDocumentRegion); return; } } } } } else { throw new StructuredDocumentRegionManagementException(); } } else {*/ IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy( oldOffset, oldLength); if (ownerEndTag != null) { ownerEndTag .setEndStructuredDocumentRegion(newStructuredDocumentRegion); } else { ownerNode .setStructuredDocumentRegion(newStructuredDocumentRegion); } //} } /** * replaceAttr method * * @param ownerIJSONObject * org.w3c.dom.IJSONObject * @param newAttr * org.w3c.dom.Attr * @param oldAttr * org.w3c.dom.Attr */ void replaceAttr(IJSONObject ownerIJSONObject, IJSONNode newAttr, IJSONNode oldAttr) { if (ownerIJSONObject == null) return; if (getStructuredDocument() == null) return; JSONObjectImpl element = (JSONObjectImpl) ownerIJSONObject; if (!element.hasStartTag()) { changeStartTag(element); return; } // if (element.isCommentTag()) { // changeStartTag(element); // return; // } // int offset = element.getStartOffset(); // int start = offset; // int end = offset; // // boolean insertSpace = false; // String attrValueClose = null; // if (oldAttr != null) { // AttrImpl impl = (AttrImpl) oldAttr; // ITextRegion nameRegion = impl.getNameRegion(); // if (nameRegion == null) // return; // must never happen // ITextRegion lastRegion = impl.getValueRegion(); // if (lastRegion != null) { // end += lastRegion.getEnd(); // } else { // lastRegion = impl.getEqualRegion(); // if (lastRegion != null) { // end += lastRegion.getEnd(); // } else { // end += nameRegion.getEnd(); // lastRegion = nameRegion; // } // } // // check there are extra space before the last attribute // IStructuredDocumentRegion flatNode = element // .getStartStructuredDocumentRegion(); // if (flatNode == null) // return; // must never happen // ITextRegionList regions = flatNode.getRegions(); // if (regions == null) // return; // must never happen // ITextRegion prevRegion = null; // ITextRegion nextRegion = null; // for (int i = 0; i < regions.size(); i++) { // ITextRegion region = regions.get(i); // if (region == nameRegion) { // if (i > 0) { // prevRegion = regions.get(i - 1); // } // } // if (region == lastRegion) { // if (i + 1 < regions.size()) { // nextRegion = regions.get(i + 1); // } // break; // } // } // boolean isLastAttr = false; // if (nextRegion != null) { // String regionType = nextRegion.getType(); // if (regionType == JSONRegionContexts.JSON_TAG_CLOSE // || regionType == JSONRegionContexts.JSON_EMPTY_TAG_CLOSE // || isNestedTagClose(regionType)) { // isLastAttr = true; // } // } // if (isLastAttr && prevRegion != null) { // start += prevRegion.getTextEnd(); // } else { // start += nameRegion.getStart(); // } // // // impl.resetRegions(ownerIJSONObject); // impl.resetRegions(element); // } else { // append attribute // IStructuredDocumentRegion flatNode = element // .getStartStructuredDocumentRegion(); // if (flatNode == null) // return; // must never happen // // attrValueClose = getAttrValueClose(element); // if (attrValueClose != null && attrValueClose.length() > 0) { // insertSpace = true; // start = flatNode.getEndOffset(); // end = start; // } else { // ITextRegionList regions = flatNode.getRegions(); // if (regions == null) // return; // must never happen // int attrStart = 0; // for (int i = regions.size() - 1; i >= 0; i--) { // ITextRegion region = regions.get(i); // String regionType = region.getType(); // if (regionType == JSONRegionContexts.JSON_TAG_CLOSE // || regionType == JSONRegionContexts.JSON_EMPTY_TAG_CLOSE // || isNestedTagClose(regionType)) // continue; // int regionEnd = region.getEnd(); // if (regionEnd == region.getTextEnd()) // insertSpace = true; // attrStart = regionEnd; // break; // } // if (attrStart == 0) // return; // not found, must never happen // start += attrStart; // end = start; // } // } // // String source = null; // if (newAttr != null) { // int size = 2; // if (attrValueClose != null) // size += attrValueClose.length(); // String name = this.generator.generateAttrName(newAttr); // if (name != null) // size += name.length(); // String value = this.generator.generateAttrValue(newAttr); // if (value != null) // size += value.length(); // StringBuffer buffer = new StringBuffer(size); // if (attrValueClose != null) // buffer.append(attrValueClose); // if (insertSpace) // buffer.append(' '); // buffer.append(name); // if (value != null) { // buffer.append('='); // buffer.append(value); // } // source = buffer.toString(); // } //replaceSource(source, start, end); } protected boolean isNestedTagClose(String regionType) { boolean result = false; return result; } /** * replaceChild method * * @param parentNode * org.w3c.dom.Node * @param newChild * org.w3c.dom.Node * @param oldChild * org.w3c.dom.Node */ void replaceChild(IJSONNode parentNode, IJSONNode newChild, IJSONNode oldChild) { if (parentNode == null) return; if (newChild == null && oldChild == null) return; if (getStructuredDocument() == null) return; int start = 0; int end = 0; String preTag = null; String postTag = null; JSONObjectImpl postIJSONObject = null; if (oldChild != null) { JSONNodeImpl node = (JSONNodeImpl) oldChild; start = node.getStartOffset(); end = node.getEndOffset(); // if (oldChild.getNodeType() == Node.TEXT_NODE) { // this.gapStructuredDocumentRegion = node // .getStructuredDocumentRegion(); // } node.resetStructuredDocumentRegions(); // reset values from // IStructuredDocumentRegion } else { JSONNodeImpl prev = (JSONNodeImpl) newChild.getPreviousSibling(); if (prev != null) { start = prev.getEndOffset(); end = start; //preTag = getCloseTag(prev); } else { // first child JSONNodeImpl next = (JSONNodeImpl) newChild.getNextSibling(); if (next != null) { start = next.getStartOffset(); end = start; if (parentNode.getNodeType() == IJSONNode.OBJECT_NODE) { // preTag = getStartCloseTag((IJSONIJSONObject) parentNode); } } else { // newly having a child if (parentNode.getNodeType() == IJSONNode.OBJECT_NODE) { IJSONObject element = (IJSONObject) parentNode; // if (element.isEmptyTag() // || isSelfClosedContainer(element)) { // empty // // tag // // format // // need to generate the start and the end tags // end = element.getEndOffset(); // start = end - 2; // for "/>" // element.setEmptyTag(false); // preTag = this.generator.generateCloseTag(element); // postTag = this.generator.generateEndTag(element); // postIJSONObject = element; // } // else if (!element.hasStartTag()) { // start = element.getStartOffset(); // end = start; // // invalid end tag or implicit tag // // need to generate the start tag // preTag = this.generator.generateStartTag(element); // if (preTag != null) { // int length = preTag.length(); // if (length > 0) { // IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy( // start, length); // element.setStartStructuredDocumentRegion(flatNode); // } // } // if (!element.hasEndTag()) { // // implicit tag // // need to generate the end tags // postTag = this.generator // .generateEndTag(element); // postIJSONObject = element; // } // } else { // start = element.getStartEndOffset(); // end = start; // preTag = getStartCloseTag(element); // if (preTag != null && preTag.length() > 0) { // if (!element.hasEndTag() // && (element.isJSPContainer() || element // .isCDATAContainer())) { // // need to generate the end tag // postTag = this.generator // .generateEndTag(element); // postIJSONObject = element; // } // } //} } // else might DOCUMENT_NODE, start and end are 0 } } } String source = null; if (newChild != null) { StringBuffer buffer = new StringBuffer(); int offset = start; if (preTag != null) { int length = preTag.length(); if (length > 0) { offset += length; buffer.append(preTag); } } JSONNodeImpl node = (JSONNodeImpl) newChild; while (node != null) { if (node.getNodeType() == IJSONNode.OBJECT_NODE) { JSONObjectImpl element = (JSONObjectImpl) node; // if (element.preferEmptyTag()) // element.setEmptyTag(true); IStructuredDocumentRegion flatNode = null; String startTag = this.generator.generateStartTag(element); if (startTag != null) { int length = startTag.length(); if (length > 0) { buffer.append(startTag); flatNode = new StructuredDocumentRegionProxy( offset, length); offset += length; } } element.setStartStructuredDocumentRegion(flatNode); } else { String content = this.generator.generateSource(node); if (content == null) content = JSONNodeImpl.EMPTY_STRING; int length = content.length(); IStructuredDocumentRegion flatNode = null; if (length > 0) { buffer.append(content); flatNode = new StructuredDocumentRegionProxy(offset, length); offset += length; } node.setStructuredDocumentRegion(flatNode); } JSONNodeImpl child = (JSONNodeImpl) node.getFirstChild(); if (child != null) { node = child; continue; } if (node.getNodeType() == IJSONNode.OBJECT_NODE) { JSONObjectImpl element = (JSONObjectImpl) node; IStructuredDocumentRegion flatNode = null; String endTag = this.generator.generateEndTag(element); if (endTag != null) { int length = endTag.length(); if (length > 0) { buffer.append(endTag); flatNode = new StructuredDocumentRegionProxy( offset, length); offset += length; } } element.setEndStructuredDocumentRegion(flatNode); } while (node != null) { if (node == newChild) { node = null; break; } JSONNodeImpl next = (JSONNodeImpl) node.getNextSibling(); if (next != null) { node = next; break; } node = (JSONNodeImpl) node.getParentNode(); if (node.getNodeType() != IJSONNode.OBJECT_NODE) continue; JSONObjectImpl element = (JSONObjectImpl) node; IStructuredDocumentRegion flatNode = null; String endTag = this.generator.generateEndTag(element); if (endTag != null) { int length = endTag.length(); if (length > 0) { buffer.append(endTag); flatNode = new StructuredDocumentRegionProxy( offset, length); offset += length; } } element.setEndStructuredDocumentRegion(flatNode); } } if (postTag != null) { int length = postTag.length(); if (length > 0) { buffer.append(postTag); if (postIJSONObject != null) { IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy( offset, length); postIJSONObject.setEndStructuredDocumentRegion(flatNode); } } } source = buffer.toString(); } if (start == end && (source == null || source.length() == 0)) { // no thing changed return; } replaceSource(source, start, end); } void replaceRegions(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) { // future_TODO: optimize JSONNodeImpl root = (JSONNodeImpl) this.model.getDocument(); this.parentNode = root; this.nextNode = (JSONNodeImpl) root.getFirstChild(); removeGapStructuredDocumentRegion(flatNode); insertGapStructuredDocumentRegionBefore(flatNode.getStart()); changeStructuredDocumentRegion(flatNode); insertGapStructuredDocumentRegionAfter(flatNode.getEnd()); } /** * Wraps IStructuredDocumentRegion.replaceText() and sets contextual * information. */ private void replaceSource(String source, int start, int end) { int inserted = 0; if (source == null) source = JSONNodeImpl.EMPTY_STRING; else inserted = source.length(); int removed = end - start; if (inserted == 0 && removed == 0) return; this.gapOffset = start; this.gapLength = removed; this.diff = inserted - removed; // Note: due to bug // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=3619 // for now assume "ignore readonly" region is ok -- assume JSON itself // checks if // ok to insert or not. In reality, we may have to make or "contains" // method more // better. Or, we may have to "perculate up" the parameter for clients // to tell us programatically // that its ok to insert/format in a read-only region. getStructuredDocument().replaceText(this.model, this.gapOffset, this.gapLength, source, true); } void replaceStructuredDocumentRegions( IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) { JSONNodeImpl root = (JSONNodeImpl) this.model.getDocument(); if (oldStructuredDocumentRegions != null) { this.parentNode = root; this.nextNode = (JSONNodeImpl) root.getFirstChild(); Enumeration e = oldStructuredDocumentRegions.elements(); while (e.hasMoreElements()) { IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e .nextElement(); if (flatNode == null) continue; removeStructuredDocumentRegion(flatNode); removeGapStructuredDocumentRegion(flatNode); } } if (newStructuredDocumentRegions != null) { this.parentNode = root; this.nextNode = (JSONNodeImpl) root.getFirstChild(); IStructuredDocumentRegion lastStructuredDocumentRegion = null; Enumeration e = newStructuredDocumentRegions.elements(); while (e.hasMoreElements()) { IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e .nextElement(); if (flatNode == null) continue; if (lastStructuredDocumentRegion == null) insertGapStructuredDocumentRegionBefore(flatNode.getStart()); insertStructuredDocumentRegion(flatNode); lastStructuredDocumentRegion = flatNode; } if (lastStructuredDocumentRegion != null) { insertGapStructuredDocumentRegionAfter(lastStructuredDocumentRegion .getEnd()); } else { insertGapStructuredDocumentRegionBefore(this.gapOffset); // make sure to restore all backuped StructuredDocumentRegions insertGapStructuredDocumentRegionAfter(this.gapOffset); } } else { this.parentNode = root; this.nextNode = (JSONNodeImpl) root.getFirstChild(); insertGapStructuredDocumentRegionBefore(this.gapOffset); // make sure to restore all backuped StructuredDocumentRegions insertGapStructuredDocumentRegionAfter(this.gapOffset); } } /** */ private void updateAttrRegions(IJSONObject element, IStructuredDocumentRegion flatNode) { // update attributes ITextRegionList regions = flatNode.getRegions(); if (regions == null) return; // NamedNodeMap attributes = element.getAttributes(); // if (attributes == null) // return; // int index = -1; // AttrImpl attr = null; // Iterator e = regions.iterator(); // while (e.hasNext()) { // ITextRegion region = (ITextRegion) e.next(); // String regionType = region.getType(); // if (regionType == JSONRegionContexts.JSON_TAG_ATTRIBUTE_NAME) { // attr = (AttrImpl) attributes.item(++index); // if (attr != null) { // attr.setNameRegion(region); // // reset other regions // attr.setEqualRegion(null); // attr.setValueRegion(null); // } // } else if (regionType == JSONRegionContexts.JSON_TAG_ATTRIBUTE_EQUALS) { // if (attr != null) // attr.setEqualRegion(region); // } else if (regionType == JSONRegionContexts.JSON_TAG_ATTRIBUTE_VALUE) { // if (attr != null) { // attr.setValueRegion(region); // attr = null; // } // } // } } }