public List collectJSONNodes(IStructuredModel model, int start, int length) { List nodes = new ArrayList(); IndexedRegion startNode = model.getIndexedRegion(start); IndexedRegion endNode = model.getIndexedRegion(start + length - 1); if (startNode == null || endNode == null) { return nodes; } if (model instanceof IJSONModel && startNode instanceof IJSONNode && endNode instanceof IJSONNode) { // JSON model IJSONNode ca = getCommonAncestor((IJSONNode) startNode, (IJSONNode) endNode); if (ca != null) { for (IJSONNode node = ca.getFirstChild(); node != null && start + length < ((IndexedRegion) node).getStartOffset(); node = node.getNextSibling()) { if (start < ((IndexedRegion) node).getEndOffset()) { nodes.add(node); } } } } return nodes; }
private static boolean isSimpleValue(IJSONNode node) { if (node == null) { return false; } return node.getNodeType() == IJSONNode.VALUE_BOOLEAN_NODE || node.getNodeType() == IJSONNode.VALUE_NULL_NODE || node.getNodeType() == IJSONNode.VALUE_NUMBER_NODE || node.getNodeType() == IJSONNode.VALUE_STRING_NODE; }
private IJSONNode getCommonAncestor(IJSONNode nodeA, IJSONNode nodeB) { if (nodeA == null || nodeB == null) { return null; } for (IJSONNode na = nodeA; na != null; na = na.getParentNode()) { for (IJSONNode ta = nodeB; ta != null; ta = ta.getParentNode()) { if (ta == na) { return ta; } } } return null; // not found }
private static boolean isArray(IJSONNode node) { if (node == null) { return false; } int nodeType = node.getNodeType(); return nodeType == IJSONNode.ARRAY_NODE; }
private static boolean isObject(IJSONNode node) { if (node == null) { return false; } int nodeType = node.getNodeType(); return nodeType == IJSONNode.OBJECT_NODE; }
private static IJSONPair findByPath(IJSONNode node, String name) { if (node == null || node.getNodeType() != IJSONNode.OBJECT_NODE) { return null; } IJSONObject obj = (IJSONObject) node; for (int i = 0; i < obj.getLength(); i++) { try { IJSONNode n = (IJSONNode) obj.getClass().getMethod("item", int.class).invoke(obj, i); if (n.getNodeType() == IJSONNode.PAIR_NODE) { IJSONPair pair = (IJSONPair) n; if (name.equals(pair.getName())) { return pair; } } } catch (Exception e) { return null; } } return null; }
private static int getEndOffset(IJSONNode parent, boolean inside) { if (parent == null) { return 0; } switch (parent.getNodeType()) { case IJSONNode.OBJECT_NODE: if (parent.hasChildNodes()) { IJSONNode lastChild = parent.getLastChild(); boolean childInside = inside && (isSimpleValue(lastChild) || (lastChild.getNodeType() == IJSONNode.PAIR_NODE && isSimpleValue(((IJSONPair) lastChild).getValue()))); return getEndOffset(lastChild, childInside); } return parent.getStartOffset() + (inside ? 1 : 0); case IJSONNode.PAIR_NODE: if (!inside) { return parent.getEndOffset(); } IJSONPair pair = (IJSONPair) parent; IJSONValue value = (IJSONValue) pair.getValue(); if (value != null) { return getEndOffset(value, false); } return pair.getEndOffset(); case IJSONNode.VALUE_BOOLEAN_NODE: case IJSONNode.VALUE_NULL_NODE: case IJSONNode.VALUE_NUMBER_NODE: case IJSONNode.VALUE_STRING_NODE: return parent.getStartOffset() + parent.getFirstStructuredDocumentRegion().getFirstRegion().getLength(); default: return parent.getEndOffset(); } }
public static void setValue(IStructuredDocument document, IJSONPath path, Object value) { IJSONModel model = null; try { model = (IJSONModel) StructuredModelManager.getModelManager().getModelForEdit(document); IJSONNode parent = model.getDocument().getFirstChild(); String[] segments = path.getSegments(); String name = null; int replaceOffset = 0; int replaceLength = 0; boolean isArray = false; int startIndex = NO_START_INDEX; StringBuilder newContent = new StringBuilder(); for (int i = 0; i < segments.length; i++) { name = segments[i]; isArray = isArray(path, i); IJSONPair node = findByPath(parent, name); if (node != null) { parent = node; IJSONNode jsonValue = node.getValue(); if (isObject(jsonValue)) { parent = jsonValue; replaceOffset = getEndOffset(parent, true); } else { if (jsonValue != null) { replaceOffset = jsonValue.getStartOffset(); replaceLength = isArray(jsonValue) ? jsonValue.getEndStructuredDocumentRegion().getEndOffset() - jsonValue.getFirstStructuredDocumentRegion().getStartOffset() : jsonValue.getFirstStructuredDocumentRegion().getFirstRegion().getLength(); } } } else { if (isObjectOrArray(parent)) { replaceOffset = getEndOffset(parent, true); if (parent.hasChildNodes()) { newContent.append(","); } } else { newContent.append(isArray ? "[" : "{"); if (startIndex == NO_START_INDEX) { startIndex = i - 1; } } newLineAndIndent(i, newContent); newContent.append("\""); newContent.append(name); newContent.append("\": "); parent = null; } } addValue(value, newContent); if (startIndex != NO_START_INDEX) { // close JSON object or Array for (int i = segments.length - 1; i > startIndex; i--) { if (i == -1) { newLineAndIndent(0, newContent); newContent.append("}"); } else { name = segments[i]; isArray = isArray(path, i); newLineAndIndent(i - 1, newContent); newContent.append(isArray ? "]" : "}"); } } } document.replaceText(document, replaceOffset, replaceLength, newContent.toString()); } finally { if (model != null) { model.releaseFromEdit(); } } }