/*******************************************************************************
* Copyright (c) 2004, 2016 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
* Angelo Zerr <angelo.zerr@gmail.com> - copied from org.eclipse.wst.css.core.internal.formatter.StyleDeclarationFormatter
* modified in order to process JSON Objects.
*******************************************************************************/
package org.eclipse.wst.json.core.internal.format;
import org.eclipse.jface.text.IRegion;
import org.eclipse.wst.json.core.cleanup.IJSONCleanupStrategy;
import org.eclipse.wst.json.core.document.IJSONArray;
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.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
public class JSONArrayFormatter extends JSONStructureFormatter {
private static JSONArrayFormatter instance;
JSONArrayFormatter() {
super();
}
@Override
protected void formatChildren(IJSONNode node, StringBuilder source) {
if (node instanceof IJSONArray) {
IJSONArray array = (IJSONArray) node;
IJSONNode child = array.getFirstChild();
while (child != null) {
if (child instanceof IJSONObject || child instanceof IJSONArray) {
formatObject(node, source, child);
if (child.getNextSibling() != null) {
int start = child.getEndOffset();
int end = child.getNextSibling().getStartOffset();
if (end > start) {
IJSONCleanupStrategy stgy = getCleanupStrategy(node);
IStructuredDocument structuredDocument = node.getOwnerDocument().getModel()
.getStructuredDocument();
CompoundRegion[] regions = getRegionsWithoutWhiteSpaces(structuredDocument,
new FormatRegion(start, end - start), stgy);
for (int i = 0; i < regions.length; i++) {
source.append(decoratedRegion(regions[i], 0, stgy));
}
}
}
String delim = getLineDelimiter(node);
source.append(delim);
source.append(getIndent(node));
} else {
formatValue(node, source, child);
}
child = child.getNextSibling();
if (child != null) {
source.append(getIndentString());
}
}
}
}
@Override
protected void formatValue(IJSONNode node, StringBuilder source, IJSONNode value) {
IJSONCleanupStrategy stgy = getCleanupStrategy(node);
IStructuredDocument structuredDocument = node.getOwnerDocument().getModel().getStructuredDocument();
int start = value.getStartOffset();
int end = value.getEndOffset();
if (value.getNextSibling() != null) {
int s = value.getEndOffset();
int e = value.getNextSibling().getStartOffset();
CompoundRegion[] regions = getRegionsWithoutWhiteSpaces(structuredDocument, new FormatRegion(s, e - s),
stgy);
if (regions.length > 0) {
end++;
}
}
CompoundRegion[] regions = getRegionsWithoutWhiteSpaces(structuredDocument,
new FormatRegion(start, end - start), stgy);
for (int i = 0; i < regions.length; i++) {
source.append(decoratedRegion(regions[i], 0, stgy));
}
source.append(getLineDelimiter(node));
source.append(getIndent(node));
}
@Override
protected void formatObject(IJSONNode node, StringBuilder source, IJSONNode jsonObject) {
IJSONCleanupStrategy stgy = getCleanupStrategy(node);
IStructuredDocument structuredDocument = node.getOwnerDocument().getModel().getStructuredDocument();
IStructuredDocumentRegion[] structuredRegions = structuredDocument
.getStructuredDocumentRegions(node.getStartOffset(), node.getEndOffset());
if (structuredRegions.length >= 2) {
int start = structuredRegions[1].getStartOffset();
int end = node.getEndOffset();
IJSONSourceFormatter formatter = (IJSONSourceFormatter) ((INodeNotifier) jsonObject)
.getAdapterFor(IJSONSourceFormatter.class);
if (formatter == null) {
formatter = JSONSourceFormatterFactory.getInstance().getSourceFormatter(jsonObject);
}
StringBuilder objectSource = formatter.format(jsonObject, new FormatRegion(start, end - start));
if (objectSource != null) {
source.append(objectSource);
}
}
}
@Override
protected void formatChildren(IJSONNode node, IRegion region, StringBuilder source) {
IJSONNode child = node.getFirstChild();
int start = region.getOffset();
int end = region.getOffset() + region.getLength();
while (child != null) {
int curEnd = child.getEndOffset();
StringBuilder childSource = null;
boolean toFinish = false;
if (start < curEnd) {
int curStart = child.getStartOffset();
if (curStart < end) {
// append child
IJSONSourceFormatter formatter = (IJSONSourceFormatter) ((INodeNotifier) child)
.getAdapterFor(IJSONSourceFormatter.class);
if (formatter == null) {
formatter = JSONSourceFormatterFactory.getInstance().getSourceFormatter(child);
}
if (includes(region, curStart, curEnd))
childSource = ((AbstractJSONSourceFormatter) formatter).formatProc(child);
else
childSource = ((AbstractJSONSourceFormatter) formatter).formatProc(child,
overlappedRegion(region, curStart, curEnd));
} else
toFinish = true;
}
if (childSource != null) {
source.append(childSource);
}
if (toFinish)
break;
child = child.getNextSibling();
}
}
@Override
protected void formatPre(IJSONNode node, StringBuilder source) {
formatPre(node, new FormatRegion(node.getStartOffset(), node.getEndOffset() - node.getStartOffset()), source);
}
@Override
protected void formatPre(IJSONNode node, IRegion region, StringBuilder source) {
IJSONCleanupStrategy stgy = getCleanupStrategy(node);
if (region.getOffset() >= 0 && region.getLength() >= 0) {
IStructuredDocument document = node.getOwnerDocument().getModel().getStructuredDocument();
CompoundRegion[] regions = getRegionsWithoutWhiteSpaces(document, region, stgy);
if (regions.length > 0 && regions[0] != null
&& regions[0].getType() == JSONRegionContexts.JSON_ARRAY_OPEN) {
source.append(decoratedRegion(regions[0], 0, stgy));
}
}
if (node instanceof IJSONArray && node.hasChildNodes()) {
source.append(getLineDelimiter(node));
source.append(getIndent(node));
source.append(getIndentString());
}
}
@Override
protected void formatPost(IJSONNode node, StringBuilder source) {
formatPost(node, new FormatRegion(node.getStartOffset(), node.getEndOffset() - node.getStartOffset()), source);
}
@Override
protected void formatPost(IJSONNode node, IRegion region, StringBuilder source) {
IJSONCleanupStrategy stgy = getCleanupStrategy(node);
if (region.getOffset() >= 0 && region.getLength() >= 0) {
IStructuredDocument document = node.getOwnerDocument().getModel().getStructuredDocument();
CompoundRegion[] regions = getRegionsWithoutWhiteSpaces(document, region, stgy);
if (regions.length > 0 && regions[regions.length - 1] != null) {
CompoundRegion r = regions[regions.length - 1];
if (r != null && r.getType() == JSONRegionContexts.JSON_ARRAY_CLOSE) {
source.append(decoratedRegion(r, 0, stgy));
}
}
}
}
public synchronized static JSONArrayFormatter getInstance() {
if (instance == null)
instance = new JSONArrayFormatter();
return instance;
}
}