Bug 494111 - Validate JSON file with JSON Schema
Change-Id: I51491c77a6f270c17f6df3b84f47e5ccb7ea13bf
Signed-off-by: Snjezana Peco <snjezana.peco@redhat.com>
Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
diff --git a/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaDocument.java b/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaDocument.java
index 5e70c98..bd8d689 100644
--- a/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaDocument.java
+++ b/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaDocument.java
@@ -13,10 +13,6 @@
import java.io.IOException;
import java.io.Reader;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import org.eclipse.json.IValidationReporter;
import org.eclipse.json.jsonpath.IJSONPath;
@@ -24,77 +20,13 @@
import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonValue;
import org.eclipse.json.schema.IJSONSchemaDocument;
import org.eclipse.json.schema.IJSONSchemaProperty;
-import org.eclipse.json.schema.JSONSchemaType;
@SuppressWarnings("serial")
public class JSONSchemaDocument extends JSONSchemaNode implements
IJSONSchemaDocument {
- private static final String DEFINITIONS = "#/definitions/"; //$NON-NLS-1$
- private final Map<String, IJSONSchemaProperty> definitions;
public JSONSchemaDocument(Reader reader) throws IOException {
super(JsonObject.readFrom(reader), null);
- this.definitions = new HashMap<String, IJSONSchemaProperty>();
- addDefinitions(getJsonObject());
- resolveReferences();
- }
-
- private void resolveReferences() {
- resolveReference(this);
- for (IJSONSchemaProperty definition : definitions.values()) {
- resolveReference(definition);
- }
- Collection<IJSONSchemaProperty> props = getProperties().values();
- for (IJSONSchemaProperty property:props) {
- resolveReference(property);
- }
- }
-
- private void resolveReference(IJSONSchemaProperty node) {
- String reference = node.getReference();
- if (reference != null) {
- String ref = reference.substring(DEFINITIONS.length());
- IJSONSchemaProperty property = definitions.get(ref);
- if (property != null) {
- for (IJSONSchemaProperty p : property.getProperties().values()) {
- node.addProperty(p);
- }
- Collection<IJSONSchemaProperty> props = property.getProperties().values();
- for (IJSONSchemaProperty p : props) {
- resolveReference(p);
- }
- }
- }
- Collection<IJSONSchemaProperty> props = node.getProperties().values();
- for (IJSONSchemaProperty p:props) {
- resolveReference(p);
- }
- List<String> references = node.getReferences();
- for (String ref:references) {
- String r = ref.substring(DEFINITIONS.length());
- IJSONSchemaProperty property = definitions.get(r);
- if (property != null) {
- for (IJSONSchemaProperty p:property.getProperties().values()) {
- node.addProperty(p);
- }
- }
- }
- }
-
- private void addDefinitions(JsonObject json) {
- Member member = null;
- JsonObject definitions = (JsonObject) json.get("definitions");
- if (definitions != null) {
- Iterator<Member> members = definitions.iterator();
- while (members.hasNext()) {
- member = members.next();
- addDefinition(new JSONSchemaProperty(member.getName(),
- (JsonObject) member.getValue(), this));
- }
- }
- }
- private void addDefinition(IJSONSchemaProperty property) {
- definitions.put(property.getName(), property);
}
@Override
@@ -128,39 +60,14 @@
return null;
}
- @Override
- public String getName() {
- return null;
- }
-
- @Override
- public String getDescription() {
- return null;
- }
-
- @Override
- public JSONSchemaType[] getType() {
- return null;
- }
-
- @Override
- public JSONSchemaType getFirstType() {
- return null;
- }
-
public void validate(JsonValue value, IValidationReporter reporter) {
// TODO Auto-generated method stub
}
@Override
- public List<String> getEnumList() {
- return null;
- }
-
- @Override
- public String getDefaultValue() {
- return null;
+ public String getName() {
+ return ""; //$NON-NLS-1$
}
}
diff --git a/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaNode.java b/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaNode.java
index 92d85f2..8f02638 100644
--- a/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaNode.java
+++ b/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaNode.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2013-2014 Angelo ZERR.
+ * Copyright (c) 2013-2016 Angelo ZERR.
* 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
@@ -13,33 +13,133 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonArray;
import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonObject;
import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonValue;
+import org.eclipse.json.schema.IJSONSchemaDocument;
import org.eclipse.json.schema.IJSONSchemaNode;
import org.eclipse.json.schema.IJSONSchemaProperty;
+import org.eclipse.json.schema.JSONSchemaType;
@SuppressWarnings("serial")
public class JSONSchemaNode extends JsonObject implements IJSONSchemaNode {
- private static final String PROPERTIES = "properties"; //$NON-NLS-1$
- private static final String REF = "$ref"; //$NON-NLS-1$
+ private Map<String, JsonValue> definitions;
private final IJSONSchemaNode parent;
private final Map<String, IJSONSchemaProperty> properties;
- private final String reference;
- private final List<String> references;
private JsonObject jsonObject;
+ protected final String description;
+ protected JSONSchemaType[] type;
+ protected String defaultValue;
+ private List<String> enumList;
public JSONSchemaNode(JsonObject jsonObject, IJSONSchemaNode parent) {
this.parent = parent;
this.jsonObject = jsonObject;
+ if (this instanceof IJSONSchemaDocument) {
+ definitions = new HashMap<String, JsonValue>();
+ addDefinitions();
+ resolveReferences(jsonObject);
+ }
this.properties = new HashMap<String, IJSONSchemaProperty>();
- this.references = new ArrayList<String>();
- this.reference = jsonObject.getString(REF, null);
- walk(jsonObject, this, true);
+ walk(jsonObject, this);
+ this.description = jsonObject.getString("description", null); //$NON-NLS-1$
+ this.type = getType(jsonObject.get(TYPE));
+ JsonValue value = jsonObject.get("default"); //$NON-NLS-1$
+ if (value != null) {
+ defaultValue = removeQuote(value);
+ }
+ value = jsonObject.get(ENUM);
+ if (value instanceof JsonArray) {
+ JsonArray array = (JsonArray) value;
+ List<JsonValue> items = array.values();
+ for (JsonValue v:items) {
+ if (v != null) {
+ if (type == null || type.length == 0) {
+ String str = v.toString();
+ if (str.startsWith(QUOTE) && str.endsWith(QUOTE)) {
+ type = new JSONSchemaType[] {JSONSchemaType.String};
+ }
+ }
+ addEnum(removeQuote(v));
+ }
+ }
+ }
+ }
+
+ private void resolveReferences(JsonObject json) {
+ Iterator<Member> members = json.iterator();
+ while (members.hasNext()) {
+ Member member = members.next();
+ JsonValue value = member.getValue();
+ resolveReferences(json, member.getName(), value);
+ }
+ }
+
+ private void resolveReferences(JsonObject parent, String name, JsonValue value) {
+ if (value instanceof JsonObject) {
+ JsonObject json = value.asObject();
+ String ref = json.getString(REF, null);
+ if (ref != null && ref.startsWith(DEFINITIONS)) {
+ String r = ref.substring(DEFINITIONS.length());
+ JsonValue v = definitions.get(r);
+ parent.set(name, v);
+ //json.remove(REF);
+ } else {
+ Iterator<Member> members = json.iterator();
+ while (members.hasNext()) {
+ Member member = members.next();
+ JsonValue v = member.getValue();
+ resolveReferences(json, member.getName(), v);
+ }
+ }
+ } else if (value instanceof JsonArray) {
+ JsonArray jsonArray = (JsonArray) value;
+ for (int i = 0; i < jsonArray.size(); i++) {
+ JsonValue item = jsonArray.get(i);
+ if (item instanceof JsonObject) {
+ JsonObject json = item.asObject();
+ String ref = json.getString(REF, null);
+ if (ref != null && ref.startsWith(DEFINITIONS)) {
+ String r = ref.substring(DEFINITIONS.length());
+ JsonValue v = definitions.get(r);
+ jsonArray.set(i, v);
+ } else {
+ resolveReferences(json);
+ }
+ }
+ }
+ }
+ }
+
+ private void addDefinitions() {
+ JsonValue defs = jsonObject.get("definitions"); //$NON-NLS-1$
+ if (defs instanceof JsonObject) {
+ Iterator<Member> members = ((JsonObject) defs).iterator();
+ while (members.hasNext()) {
+ Member member = members.next();
+ JsonValue value = member.getValue();
+ if (value instanceof JsonObject) {
+ definitions.put(member.getName(), member.getValue());
+ }
+ }
+ }
+ }
+
+ private void walk(JsonObject json, IJSONSchemaNode schemaNode) {
+ JsonObject properties = (JsonObject) json.get(PROPERTIES);
+ addProperties(schemaNode, properties);
+ add(json, schemaNode, ALL_OF);
+ add(json, schemaNode, ANY_OF);
+ add(json, schemaNode, ONE_OF);
+ JsonValue notMember = json.get(NOT);
+ if (notMember != null) {
+ walk(notMember.asObject(), schemaNode);
+ }
}
private void add(JsonObject jsonObject, IJSONSchemaNode schemaNode, String pref) {
@@ -50,59 +150,21 @@
while (iter.hasNext()) {
JsonValue value = iter.next();
if (value != null) {
- String ref = value.asObject().getString(REF, null);
- if (ref != null) {
- references.add(ref);
- } else {
- walk(value.asObject(), schemaNode, true);
- }
+ walk(value.asObject(), schemaNode);
}
}
}
}
- private void walk(JsonObject json, IJSONSchemaNode schemaNode, boolean add) {
- JsonObject properties = (JsonObject) json.get(PROPERTIES);
- addProperties(schemaNode, properties, add);
- if (properties == null) {
- JsonObject items = (JsonObject) json.get("items"); //$NON-NLS-1$
- if (items != null) {
- properties = (JsonObject) items.get(PROPERTIES);
- addProperties(schemaNode, properties, add);
- String ref = items.getString(REF, null);
- if (ref != null) {
- if (add) {
- schemaNode.getReferences().add(ref);
- } else {
- schemaNode.getReferences().remove(ref);
- }
- } else {
- walk(items, schemaNode, add);
- }
- }
- }
- add(json, schemaNode, "allOf"); //$NON-NLS-1$
- add(json, schemaNode, "anyOf"); //$NON-NLS-1$
- add(json, schemaNode, "oneOf"); //$NON-NLS-1$
- JsonValue notMember = json.get("not"); //$NON-NLS-1$
- if (notMember != null) {
- walk(notMember.asObject(), schemaNode, false);
- }
- }
-
- private void addProperties(IJSONSchemaNode schemaNode, JsonObject properties, boolean add) {
+ private void addProperties(IJSONSchemaNode schemaNode, JsonObject properties) {
if (properties == null) {
return;
}
Iterator<Member> members = properties.iterator();
while (members.hasNext()) {
Member member = members.next();
- if (add) {
- schemaNode.addProperty(
- new JSONSchemaProperty(member.getName(), (JsonObject) member.getValue(), schemaNode));
- } else {
- schemaNode.getProperties().remove(member.getName());
- }
+ schemaNode
+ .addProperty(new JSONSchemaProperty(member.getName(), (JsonObject) member.getValue(), schemaNode));
}
}
@@ -132,17 +194,112 @@
}
@Override
- public String getReference() {
- return reference;
- }
-
- @Override
- public List<String> getReferences() {
- return references;
- }
-
- @Override
public Map<String, IJSONSchemaProperty> getProperties() {
return properties;
}
+
+ protected String[] getRequired(JsonValue value) {
+ if (value == null) {
+ return null;
+ }
+ List<String> names = new ArrayList<String>();
+ if (value.isString()) {
+ String s = value.asString();
+ names.add(s);
+ } else if (value.isArray()) {
+ JsonArray array = (JsonArray) value;
+ for (JsonValue item : array) {
+ if (item.isString()) {
+ String s = item.asString();
+ names.add(s);
+ }
+ }
+ }
+ return names.toArray(new String[0]);
+ }
+
+ protected String removeQuote(JsonValue value) {
+ String str = value.toString();
+ if (str.startsWith(QUOTE)) {
+ str = str.substring(1);
+ }
+ if (str.endsWith(QUOTE)) {
+ str = str.substring(0, str.length()-1);
+ }
+ return str;
+ }
+
+ public static JSONSchemaType[] getType(JsonValue value) {
+ if (value == null) {
+ return JSONSchemaType.EMPTY_TYPES;
+ }
+ JSONSchemaType t = null;
+ List<JSONSchemaType> types = new ArrayList<JSONSchemaType>();
+ if (value.isString()) {
+ t = JSONSchemaType.getType(value.asString());
+ if (t != null) {
+ types.add(t);
+ }
+ } else if (value.isArray()) {
+ JsonArray array = (JsonArray) value;
+ for (JsonValue item : array) {
+ t = JSONSchemaType.getType(item.asString());
+ if (t != null) {
+ types.add(t);
+ }
+ }
+ }
+ return types.toArray(JSONSchemaType.EMPTY_TYPES);
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public JSONSchemaType[] getType() {
+ return type;
+ }
+
+ @Override
+ public JSONSchemaType getFirstType() {
+ if (type == null) {
+ return null;
+ }
+ if (type.length == 0) {
+ return null;
+ }
+ return type[0];
+ }
+
+ @Override
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ @Override
+ public List<String> getEnumList() {
+ return enumList;
+ }
+
+ public void addEnum(String item) {
+ if (enumList == null) {
+ enumList = new LinkedList<String>();
+ }
+ this.enumList.add(item);
+ }
+
+ @Override
+ public IJSONSchemaDocument getSchemaDocument() {
+ if (this instanceof IJSONSchemaDocument) {
+ return (IJSONSchemaDocument) this;
+ }
+ IJSONSchemaNode p = getParent();
+ if (p != null) {
+ return p.getSchemaDocument();
+ }
+ return null;
+ }
+
}
diff --git a/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaProperty.java b/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaProperty.java
index 330f8880..a32da70 100644
--- a/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaProperty.java
+++ b/bundles/org.eclipse.json/src/org/eclipse/json/impl/schema/JSONSchemaProperty.java
@@ -10,88 +10,19 @@
*/
package org.eclipse.json.impl.schema;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonArray;
import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonObject;
-import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonValue;
import org.eclipse.json.schema.IJSONSchemaNode;
import org.eclipse.json.schema.IJSONSchemaProperty;
-import org.eclipse.json.schema.JSONSchemaType;
@SuppressWarnings("serial")
public class JSONSchemaProperty extends JSONSchemaNode implements
IJSONSchemaProperty {
- private static final String QUOTE = "\""; //$NON-NLS-1$
- private final String name;
- private final String description;
- private JSONSchemaType[] type;
- private String defaultValue;
- private List<String> enumList;
-
+ protected final String name;
public JSONSchemaProperty(String name, JsonObject jsonObject,
IJSONSchemaNode parent) {
super(jsonObject, parent);
this.name = name;
- this.description = jsonObject.getString("description", null); //$NON-NLS-1$
- this.type = getType(jsonObject.get("type")); //$NON-NLS-1$
- JsonValue value = jsonObject.get("default"); //$NON-NLS-1$
- if (value != null) {
- defaultValue = removeQuote(value);
- }
- value = jsonObject.get("enum"); //$NON-NLS-1$
- if (value instanceof JsonArray) {
- JsonArray array = (JsonArray) value;
- List<JsonValue> items = array.values();
- for (JsonValue v:items) {
- if (v != null) {
- if (type == null || type.length == 0) {
- String str = v.toString();
- if (str.startsWith(QUOTE) && str.endsWith(QUOTE)) {
- type = new JSONSchemaType[] {JSONSchemaType.String};
- }
- }
- addEnum(removeQuote(v));
- }
- }
- }
- }
-
- private String removeQuote(JsonValue value) {
- String str = value.toString();
- if (str.startsWith(QUOTE)) {
- str = str.substring(1);
- }
- if (str.endsWith(QUOTE)) {
- str = str.substring(0, str.length()-1);
- }
- return str;
- }
-
- private JSONSchemaType[] getType(JsonValue value) {
- if (value == null) {
- return JSONSchemaType.EMPTY_TYPES;
- }
- JSONSchemaType t = null;
- List<JSONSchemaType> types = new ArrayList<JSONSchemaType>();
- if (value.isString()) {
- t = JSONSchemaType.getType(value.asString());
- if (t != null) {
- types.add(t);
- }
- } else if (value.isArray()) {
- JsonArray array = (JsonArray) value;
- for (JsonValue item : array) {
- t = JSONSchemaType.getType(item.asString());
- if (t != null) {
- types.add(t);
- }
- }
- }
- return types.toArray(JSONSchemaType.EMPTY_TYPES);
}
@Override
@@ -99,39 +30,4 @@
return name;
}
- @Override
- public String getDescription() {
- return description;
- }
-
- @Override
- public JSONSchemaType[] getType() {
- return type;
- }
-
- @Override
- public JSONSchemaType getFirstType() {
- if (type == null) {
- return null;
- }
- if (type.length == 0) {
- return null;
- }
- return type[0];
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public List<String> getEnumList() {
- return enumList;
- }
-
- public void addEnum(String item) {
- if (enumList == null) {
- enumList = new LinkedList<String>();
- }
- this.enumList.add(item);
- }
}
diff --git a/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaNode.java b/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaNode.java
index edd22cf..040c669 100644
--- a/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaNode.java
+++ b/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaNode.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2013-2014 Angelo ZERR.
+ * Copyright (c) 2013-2016 Angelo ZERR.
* 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
@@ -17,19 +17,56 @@
public interface IJSONSchemaNode {
+ static final String NOT = "not"; //$NON-NLS-1$
+ static final String ONE_OF = "oneOf"; //$NON-NLS-1$
+ static final String ANY_OF = "anyOf"; //$NON-NLS-1$
+ static final String ALL_OF = "allOf"; //$NON-NLS-1$
+ static final String TYPE = "type"; //$NON-NLS-1$
+ static final String REQUIRED = "required"; //$NON-NLS-1$
+ static final String MIN_PROPERTIES = "minProperties"; //$NON-NLS-1$
+ static final String MAX_PROPERTIES = "maxProperties"; //$NON-NLS-1$
+ static final String PATTERN = "pattern"; //$NON-NLS-1$
+ static final String MIN_LENGTH = "minLength"; //$NON-NLS-1$
+ static final String MAX_LENGTH = "maxLength"; //$NON-NLS-1$
+ static final String MULTIPLEOF = "multipleOf"; //$NON-NLS-1$
+ static final String MAXIMUM = "maximum"; //$NON-NLS-1$
+ static final String EXCLUSIVE_MAXIMUM = "exclusiveMaximum"; //$NON-NLS-1$
+ static final String MINIMUM = "minimum"; //$NON-NLS-1$
+ static final String EXCLUSIVE_MINIMUM = "exclusiveMinimum"; //$NON-NLS-1$
+ static final String MIN_ITEMS = "minItems"; //$NON-NLS-1$
+ static final String MAX_ITEMS = "maxItems"; //$NON-NLS-1$
+ static final String UNIQUE_ITEMS = "uniqueItems"; //$NON-NLS-1$
+ static final String ADDITIONAL_ITEMS = "additionalItems"; //$NON-NLS-1$
+ static final String ITEMS = "items"; //$NON-NLS-1$
+ static final String ADDITIONAL_PROPERTIES = "additionalProperties"; //$NON-NLS-1$
+ static final String PATTERN_PROPERTIES = "patternProperties"; //$NON-NLS-1$
+ static final String ENUM = "enum"; //$NON-NLS-1$
+ String PROPERTIES = "properties"; //$NON-NLS-1$
+ String REF = "$ref"; //$NON-NLS-1$
+ String QUOTE = "\""; //$NON-NLS-1$
+ String DEFINITIONS = "#/definitions/"; //$NON-NLS-1$
+
+ String getDescription();
+
+ JSONSchemaType[] getType();
+
+ JSONSchemaType getFirstType();
+
+ List<String> getEnumList();
+
+ String getDefaultValue();
+
IJSONSchemaNode getParent();
IJSONSchemaProperty[] getPropertyValues();
- List<String> getReferences();
-
Map<String, IJSONSchemaProperty> getProperties();
- String getReference();
-
void setJsonObject(JsonObject jsonObject);
JsonObject getJsonObject();
void addProperty(IJSONSchemaProperty property);
+
+ IJSONSchemaDocument getSchemaDocument();
}
diff --git a/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaProperty.java b/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaProperty.java
index dffaa6c..4ec26dd 100644
--- a/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaProperty.java
+++ b/bundles/org.eclipse.json/src/org/eclipse/json/schema/IJSONSchemaProperty.java
@@ -10,22 +10,10 @@
*/
package org.eclipse.json.schema;
-import java.util.List;
-
public interface IJSONSchemaProperty extends IJSONSchemaNode {
IJSONSchemaProperty[] EMPTY_PROPERTY = new IJSONSchemaProperty[0];
-
+
String getName();
- String getDescription();
-
- JSONSchemaType[] getType();
-
- JSONSchemaType getFirstType();
-
- List<String> getEnumList();
-
- public String getDefaultValue();
-
}
diff --git a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/preferences/JSONCorePreferenceInitializer.java b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/preferences/JSONCorePreferenceInitializer.java
index 3c38a36..4144811 100644
--- a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/preferences/JSONCorePreferenceInitializer.java
+++ b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/preferences/JSONCorePreferenceInitializer.java
@@ -30,6 +30,7 @@
// Validation preferences
node.putBoolean(JSONCorePreferenceNames.SYNTAX_VALIDATION, false);
+ node.putBoolean(JSONCorePreferenceNames.SCHEMA_VALIDATION, false);
node.putInt(JSONCorePreferenceNames.MISSING_BRACKET, 2);
// formatting preferences
diff --git a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/schema/SchemaProcessorRegistryReader.java b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/schema/SchemaProcessorRegistryReader.java
index c350eb1..fdaec89 100644
--- a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/schema/SchemaProcessorRegistryReader.java
+++ b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/schema/SchemaProcessorRegistryReader.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2013-2014 Angelo ZERR.
+ * Copyright (c) 2013, 2016 Angelo ZERR.
* 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
@@ -11,6 +11,8 @@
package org.eclipse.wst.json.core.internal.schema;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
@@ -22,9 +24,13 @@
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.json.core.JSONCorePlugin;
+import org.eclipse.wst.json.core.document.IJSONDocument;
import org.eclipse.wst.json.core.document.IJSONModel;
import org.eclipse.wst.json.core.document.IJSONNode;
+import org.eclipse.wst.json.core.document.IJSONPair;
+import org.eclipse.wst.json.core.document.IJSONValue;
import org.eclipse.wst.json.core.internal.Logger;
+import org.eclipse.wst.json.core.util.JSONUtil;
public class SchemaProcessorRegistryReader {
@@ -58,6 +64,30 @@
if (processor == null) {
return null;
}
+ IJSONDocument document = model.getDocument();
+ IJSONNode jsonObject = document.getFirstChild();
+ if (jsonObject != null) {
+ IJSONNode child = jsonObject.getFirstChild();
+ while (child != null) {
+ if (child instanceof IJSONPair) {
+ IJSONPair pair = (IJSONPair) child;
+ String name = pair.getName();
+ IJSONValue valueNode = pair.getValue();
+ if (valueNode != null && "$schema".equals(name)) { //$NON-NLS-1$
+ String schema = JSONUtil.getString(valueNode);
+ try {
+ if (schema != null) {
+ schema = URIHelper.addImpliedFileProtocol(schema);
+ new URL(schema);
+ return processor.getSchema(schema);
+ }
+ } catch (MalformedURLException e) {
+ }
+ }
+ }
+ child = child.getNextSibling();
+ }
+ }
String base = model == null || model.getResolver() == null ?
null : model.getResolver().getFileBaseLocation();
/**
diff --git a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/validation/eclipse/Validator.java b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/validation/eclipse/Validator.java
index f200af1..f16f034 100644
--- a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/validation/eclipse/Validator.java
+++ b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/validation/eclipse/Validator.java
@@ -12,30 +12,73 @@
*******************************************************************************/
package org.eclipse.wst.json.core.internal.validation.eclipse;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.json.impl.schema.JSONSchemaNode;
+import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonArray;
+import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonObject;
+import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonObject.Member;
+import org.eclipse.json.provisonnal.com.eclipsesource.json.JsonValue;
+import org.eclipse.json.schema.IJSONSchemaDocument;
+import org.eclipse.json.schema.IJSONSchemaNode;
+import org.eclipse.json.schema.IJSONSchemaProperty;
+import org.eclipse.json.schema.JSONSchemaType;
import org.eclipse.wst.json.core.JSONCorePlugin;
+import org.eclipse.wst.json.core.document.IJSONArray;
+import org.eclipse.wst.json.core.document.IJSONDocument;
+import org.eclipse.wst.json.core.document.IJSONModel;
+import org.eclipse.wst.json.core.document.IJSONNode;
+import org.eclipse.wst.json.core.document.IJSONObject;
+import org.eclipse.wst.json.core.document.IJSONPair;
+import org.eclipse.wst.json.core.document.IJSONStringValue;
+import org.eclipse.wst.json.core.document.IJSONValue;
+import org.eclipse.wst.json.core.internal.schema.SchemaProcessorRegistryReader;
import org.eclipse.wst.json.core.internal.validation.JSONNestedValidatorContext;
import org.eclipse.wst.json.core.internal.validation.JSONValidationConfiguration;
+import org.eclipse.wst.json.core.internal.validation.JSONValidationInfo;
import org.eclipse.wst.json.core.internal.validation.JSONValidationReport;
import org.eclipse.wst.json.core.internal.validation.core.AbstractNestedValidator;
import org.eclipse.wst.json.core.internal.validation.core.NestedValidatorContext;
import org.eclipse.wst.json.core.internal.validation.core.ValidationMessage;
import org.eclipse.wst.json.core.internal.validation.core.ValidationReport;
import org.eclipse.wst.json.core.preferences.JSONCorePreferenceNames;
+import org.eclipse.wst.json.core.util.JSONUtil;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.validation.ValidationResult;
import org.eclipse.wst.validation.ValidationState;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
public class Validator extends AbstractNestedValidator {
+ private static final String CLOSE_BRACKET = "]"; //$NON-NLS-1$
+ private static final String OPEN_BRACKET = "["; //$NON-NLS-1$
+ private static final String COMMA = ","; //$NON-NLS-1$
private static final String JSON_VALIDATOR_CONTEXT = "org.eclipse.wst.json.core.validatorContext"; //$NON-NLS-1$
protected int indicateNoGrammar = 0;
private IScopeContext[] fPreferenceScopes = null;
@@ -45,81 +88,786 @@
super.setupValidation(context);
fPreferenceScopes = createPreferenceScopes(context);
indicateNoGrammar = Platform.getPreferencesService().getInt(
- JSONCorePlugin.getDefault().getBundle().getSymbolicName(),
- JSONCorePreferenceNames.INDICATE_NO_GRAMMAR, 0,
- fPreferenceScopes);
+ JSONCorePlugin.getDefault().getBundle().getSymbolicName(), JSONCorePreferenceNames.INDICATE_NO_GRAMMAR,
+ 0, fPreferenceScopes);
}
- protected IScopeContext[] createPreferenceScopes(
- NestedValidatorContext context) {
+ protected IScopeContext[] createPreferenceScopes(NestedValidatorContext context) {
if (context != null) {
final IProject project = context.getProject();
if (project != null && project.isAccessible()) {
final ProjectScope projectScope = new ProjectScope(project);
- if (projectScope.getNode(
- JSONCorePlugin.getDefault().getBundle()
- .getSymbolicName()).getBoolean(
- JSONCorePreferenceNames.USE_PROJECT_SETTINGS, false))
- return new IScopeContext[] { projectScope,
- new InstanceScope(), new DefaultScope() };
+ if (projectScope.getNode(JSONCorePlugin.getDefault().getBundle().getSymbolicName())
+ .getBoolean(JSONCorePreferenceNames.USE_PROJECT_SETTINGS, false))
+ return new IScopeContext[] { projectScope, new InstanceScope(), new DefaultScope() };
}
}
return new IScopeContext[] { new InstanceScope(), new DefaultScope() };
}
@Override
- public ValidationReport validate(String uri, InputStream inputstream,
- NestedValidatorContext context) {
+ public ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context) {
return validate(uri, inputstream, context, null);
}
@Override
- public ValidationReport validate(String uri, InputStream inputstream,
- NestedValidatorContext context, ValidationResult result) {
+ public ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context,
+ ValidationResult result) {
JSONValidator validator = JSONValidator.getInstance();
-
JSONValidationConfiguration configuration = new JSONValidationConfiguration();
- // try {
- // // Preferences pluginPreferences =
- // // JSONCorePlugin.getDefault().getPluginPreferences();
- // configuration.setFeature(
- // JSONValidationConfiguration.INDICATE_NO_GRAMMAR,
- // indicateNoGrammar);
- // final IPreferencesService preferencesService = Platform
- // .getPreferencesService();
- // configuration
- // .setFeature(
- // JSONValidationConfiguration.INDICATE_NO_DOCUMENT_ELEMENT,
- // preferencesService
- // .getInt(JSONCorePlugin.getDefault()
- // .getBundle().getSymbolicName(),
- // JSONCorePreferenceNames.INDICATE_NO_DOCUMENT_ELEMENT,
- // -1, fPreferenceScopes));
- // configuration.setFeature(JSONValidationConfiguration.USE_XINCLUDE,
- // preferencesService.getBoolean(JSONCorePlugin.getDefault()
- // .getBundle().getSymbolicName(),
- // JSONCorePreferenceNames.USE_XINCLUDE, false,
- // fPreferenceScopes));
- // configuration
- // .setFeature(
- // JSONValidationConfiguration.HONOUR_ALL_SCHEMA_LOCATIONS,
- // preferencesService
- // .getBoolean(
- // JSONCorePlugin.getDefault()
- // .getBundle()
- // .getSymbolicName(),
- // JSONCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS,
- // true, fPreferenceScopes));
- // } catch (Exception e) {
- // // TODO: Unable to set the preference. Log this problem.
- // }
-
- JSONValidationReport valreport = validator.validate(uri, inputstream,
- configuration, result, context);
-
+ JSONValidationReport valreport = validator.validate(uri, inputstream, configuration, result, context);
+ String prefs = JSONCorePlugin.getDefault().getBundle().getSymbolicName();
+ IEclipsePreferences modelPreferences = InstanceScope.INSTANCE.getNode(prefs);
+ boolean validateSchema = modelPreferences.getBoolean(JSONCorePreferenceNames.SCHEMA_VALIDATION, false);
+ if (validateSchema) {
+ IJSONModel model = null;
+ try {
+ IStructuredModel temp = getModel(uri);
+ if (!(temp instanceof IJSONModel)) {
+ return valreport;
+ }
+ model = (IJSONModel) temp;
+ IJSONSchemaDocument schemaDocument = SchemaProcessorRegistryReader.getInstance()
+ .getSchemaDocument(model);
+ if (schemaDocument != null) {
+ JSONValidationInfo valinfo = null;
+ if (valreport instanceof JSONValidationInfo) {
+ valinfo = (JSONValidationInfo) valreport;
+ } else {
+ valinfo = new JSONValidationInfo(uri);
+ }
+ validate(model, schemaDocument, valinfo);
+ // ValidationMessage[] messages =
+ // valreport.getValidationMessages();
+ return valreport;
+ }
+ } catch (IOException e) {
+ logWarning(e);
+ return valreport;
+ } finally {
+ if (model != null) {
+ model.releaseFromRead();
+ }
+ }
+ }
return valreport;
}
+ private void validate(IJSONModel model, IJSONSchemaProperty schemaProperty, JSONValidationInfo valinfo) {
+ IJSONDocument document = model.getDocument();
+ IJSONNode node = document.getFirstChild();
+ while (node != null) {
+ validate(node, schemaProperty, valinfo);
+ node = node.getNextSibling();
+ }
+ }
+
+ private void validate(IJSONNode node, IJSONSchemaProperty schemaProperty, JSONValidationInfo valinfo) {
+ if (node == null || schemaProperty == null) {
+ return;
+ }
+ JsonObject schema = schemaProperty.getJsonObject();
+ validate(node, schema, valinfo);
+ IJSONNode child = node.getFirstChild();
+ while (child != null) {
+ IJSONSchemaProperty property = schemaProperty.getSchemaDocument().getProperty(child.getPath());
+ validate(child, property, valinfo);
+ if (child instanceof IJSONPair) {
+ IJSONValue value = ((IJSONPair) child).getValue();
+ if (value instanceof IJSONObject) {
+ IJSONSchemaProperty prop = schemaProperty.getSchemaDocument().getProperty(value.getPath());
+ validate(value, prop, valinfo);
+ }
+ }
+ child = child.getNextSibling();
+ }
+ }
+
+ private void validate(IJSONNode node, JsonObject schema, JSONValidationInfo valinfo) {
+ Iterator<Member> members = schema.iterator();
+ while (members.hasNext()) {
+ Member member = members.next();
+ validate(node, schema, member, valinfo);
+ }
+ }
+
+ private void validate(IJSONNode node, JsonObject schema, Member member, JSONValidationInfo valinfo) {
+ if (IJSONSchemaNode.ALL_OF.equals(member.getName()) && member.getValue() instanceof JsonArray) {
+ JsonArray jsonArray = (JsonArray) member.getValue();
+ Iterator<JsonValue> iter = jsonArray.iterator();
+ while (iter.hasNext()) {
+ JsonValue value = iter.next();
+ if (value instanceof JsonObject) {
+ validate(node, (JsonObject) value, valinfo);
+ }
+ }
+ }
+ if (IJSONSchemaNode.ANY_OF.equals(member.getName()) && member.getValue() instanceof JsonArray) {
+ JsonArray jsonArray = (JsonArray) member.getValue();
+ Iterator<JsonValue> iter = jsonArray.iterator();
+ while (iter.hasNext()) {
+ JsonValue value = iter.next();
+ if (value instanceof JsonObject) {
+ JSONValidationInfo info = new JSONValidationInfo("");
+ validate(node, (JsonObject) value, info);
+ if (info.getValidationMessages() == null || info.getValidationMessages().length == 0) {
+ return;
+ }
+ }
+ }
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Matches a schema that is not allowed", line, 0, offset == 0 ? 1 : offset);
+ }
+ if (IJSONSchemaNode.ONE_OF.equals(member.getName()) && member.getValue() instanceof JsonArray) {
+ JsonArray jsonArray = (JsonArray) member.getValue();
+ Iterator<JsonValue> iter = jsonArray.iterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ JsonValue value = iter.next();
+ if (value instanceof JsonObject) {
+ JSONValidationInfo info = new JSONValidationInfo("");
+ validate(node, (JsonObject) value, info);
+ if (info.getValidationMessages() == null || info.getValidationMessages().length == 0) {
+ count = count + 1;
+ }
+ }
+ }
+ if (count != 1) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Matches a schema that is not allowed", line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ if (IJSONSchemaNode.NOT.equals(member.getName()) && member.getValue() instanceof JsonObject) {
+ JsonObject json = (JsonObject) member.getValue();
+ JSONValidationInfo info = new JSONValidationInfo("");
+ validate(node, json, info);
+ if (info.getValidationMessages() == null || info.getValidationMessages().length == 0) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Matches a schema that is not allowed", line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ if (IJSONSchemaNode.TYPE.equals(member.getName())) {
+ validateType(node, member, valinfo);
+ }
+ if (IJSONSchemaNode.ENUM.equals(member.getName())) {
+ validateEnum(node, schema, valinfo);
+ }
+ if (node.getNodeType() == IJSONNode.OBJECT_NODE) {
+ if (IJSONSchemaNode.REQUIRED.equals(member.getName())) {
+ validateRequired(node, schema, valinfo);
+ }
+ if (IJSONSchemaNode.MAX_PROPERTIES.equals(member.getName())) {
+ validateMaxProperties(node, schema, valinfo);
+ }
+ if (IJSONSchemaNode.MIN_PROPERTIES.equals(member.getName())) {
+ validateMinProperties(node, schema, valinfo);
+ }
+ if (IJSONSchemaNode.ADDITIONAL_PROPERTIES.equals(member.getName())) {
+ validateAdditionalProperties(node, schema, member.getValue(), valinfo);
+ }
+ }
+ if (node.getNodeType() == IJSONNode.PAIR_NODE) {
+ IJSONValue value = ((IJSONPair) node).getValue();
+ JSONSchemaType[] types = JSONSchemaNode.getType(schema.get(IJSONSchemaNode.TYPE));
+ if (value != null) {
+ if (value.getNodeType() == IJSONNode.VALUE_STRING_NODE && isType(types, JSONSchemaType.String)) {
+ validateString(node, schema, member, valinfo, value);
+ }
+ if (value.getNodeType() == IJSONNode.VALUE_NUMBER_NODE
+ && (isType(types, JSONSchemaType.Integer) || isType(types, JSONSchemaType.Number))) {
+ validateNumber(node, schema, member, valinfo, value);
+ }
+ if (value.getNodeType() == IJSONNode.ARRAY_NODE && isType(types, JSONSchemaType.Array)) {
+ validateArray(node, schema, member, valinfo, value);
+ }
+ }
+ }
+ }
+
+ private void validateAdditionalProperties(IJSONNode node, JsonObject schema, JsonValue value,
+ JSONValidationInfo valinfo) {
+ if (value != null && value.isBoolean() && !value.asBoolean()) {
+ Set<String> s = getProperties(node);
+ Set<String> p = getProperties(schema.get(IJSONSchemaNode.PROPERTIES));
+ Set<String> pp = getProperties(schema.get(IJSONSchemaNode.PATTERN_PROPERTIES));
+ for (String string : p) {
+ if (s.contains(string)) {
+ s.remove(string);
+ }
+ }
+ for (String patternStr : pp) {
+ Pattern pattern = Pattern.compile(patternStr);
+ Iterator<String> iter = s.iterator();
+ while (iter.hasNext()) {
+ String ss = iter.next();
+ if (ss != null) {
+ Matcher matcher = pattern.matcher(ss);
+ if (matcher.find()) {
+ iter.remove();
+ }
+ }
+ }
+ }
+ for (String string : s) {
+ if ("$schema".equals(string)) { //$NON-NLS-1$
+ continue;
+ }
+ IJSONNode n = node.getFirstChild();
+ while (n != null) {
+ if (n instanceof IJSONPair) {
+ IJSONPair pair = (IJSONPair) n;
+ if (string.equals(pair.getName())) {
+ break;
+ }
+ }
+ n = n.getNextSibling();
+ }
+ if (n == null) {
+ node = n;
+ }
+ int offset = n.getStartOffset();
+ int line = n.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Property " + string + " is not allowed", line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private Set<String> getProperties(JsonValue value) {
+ Set<String> result = new HashSet<String>();
+ if (value instanceof JsonObject) {
+ Iterator<Member> members = ((JsonObject) value).iterator();
+ while (members.hasNext()) {
+ result.add(members.next().getName());
+ }
+ }
+ return result;
+ }
+
+ private void validateArray(IJSONNode node, JsonObject schema, Member member, JSONValidationInfo valinfo,
+ IJSONValue value) {
+ if (IJSONSchemaNode.ITEMS.equals(member.getName())) {
+ validateItems(node, schema, value, member.getValue(), valinfo);
+ }
+ if (IJSONSchemaNode.MAX_ITEMS.equals(member.getName())) {
+ validateMaxItems(node, schema, value, member.getValue(), valinfo);
+ }
+ if (IJSONSchemaNode.MIN_ITEMS.equals(member.getName())) {
+ validateMinItems(node, schema, value, member.getValue(), valinfo);
+ }
+ if (IJSONSchemaNode.UNIQUE_ITEMS.equals(member.getName())) {
+ validateUniqueItems(node, schema, value, member.getValue(), valinfo);
+ }
+ }
+
+ private void validateMaxItems(IJSONNode node, JsonObject schema, IJSONValue value, JsonValue memberValue,
+ JSONValidationInfo valinfo) {
+ if (memberValue != null && memberValue.isNumber() && memberValue.asInt() > 0) {
+ if (value instanceof IJSONArray) {
+ int instanceSize = getSize((IJSONArray) value);
+ int size = memberValue.asInt();
+ if (instanceSize > size) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Array has too many items. Expected " + size + " or fewer", line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+ }
+
+ private void validateMinItems(IJSONNode node, JsonObject schema, IJSONValue value, JsonValue memberValue,
+ JSONValidationInfo valinfo) {
+ if (memberValue != null && memberValue.isNumber() && memberValue.asInt() > 0) {
+ if (value instanceof IJSONArray) {
+ int instanceSize = getSize((IJSONArray) value);
+ int size = memberValue.asInt();
+ if (instanceSize < size) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Array has too few items. Expected " + size + " or more", line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+ }
+
+ private void validateUniqueItems(IJSONNode node, JsonObject schema, IJSONValue value, JsonValue memberValue,
+ JSONValidationInfo valinfo) {
+ if (memberValue != null && memberValue.isBoolean() && memberValue.asBoolean()) {
+ if (value instanceof IJSONArray) {
+ Set<String> instanceValues = new HashSet<String>();
+ IJSONNode child = value.getFirstChild();
+ int instanceSize = 0;
+ while (child != null) {
+ instanceSize = instanceSize + 1;
+ instanceValues.add(JSONUtil.getString(child));
+ child = child.getNextSibling();
+ }
+ ;
+ if (instanceSize != instanceValues.size()) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Array has duplicate items", line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ }
+ }
+
+ private void validateItems(IJSONNode node, JsonObject schema, IJSONValue value, JsonValue memberValue,
+ JSONValidationInfo valinfo) {
+ JsonValue additionalItems = schema.get(IJSONSchemaNode.ADDITIONAL_ITEMS);
+ if (additionalItems != null && additionalItems.isBoolean() && !additionalItems.asBoolean()) {
+ if (memberValue != null && memberValue.isArray()) {
+ if (value instanceof IJSONArray) {
+ int instanceSize = getSize((IJSONArray) value);
+ int size = memberValue.asArray().size();
+ if (instanceSize > size) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Array has too many items. Expected " + size + " or fewer", line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+ }
+ }
+
+ private int getSize(IJSONArray instance) {
+ if (instance == null) {
+ return 0;
+ }
+ int instanceSize = 0;
+ IJSONNode child = instance.getFirstChild();
+ while (child != null) {
+ instanceSize = instanceSize + 1;
+ child = child.getNextSibling();
+ }
+ return instanceSize;
+ }
+
+ private void validateNumber(IJSONNode node, JsonObject schema, Member member, JSONValidationInfo valinfo,
+ IJSONValue value) {
+ if (IJSONSchemaNode.MULTIPLEOF.equals(member.getName())) {
+ validateMultipleOf(node, schema, value, valinfo);
+ }
+ if (IJSONSchemaNode.MAXIMUM.equals(member.getName())) {
+ validateMaximum(node, schema, value, valinfo);
+ }
+ if (IJSONSchemaNode.MINIMUM.equals(member.getName())) {
+ validateMinimum(node, schema, value, valinfo);
+ }
+ }
+
+ private void validateMaximum(IJSONNode node, JsonObject schema, IJSONValue valueNode, JSONValidationInfo valinfo) {
+ double maximum;
+ try {
+ maximum = schema.getDouble(IJSONSchemaNode.MAXIMUM, Double.MIN_VALUE);
+ } catch (Exception e) {
+ maximum = Double.MIN_VALUE;
+ }
+ if (maximum > Double.MIN_VALUE) {
+ boolean exclusiveMaximum;
+ try {
+ exclusiveMaximum = schema.getBoolean(IJSONSchemaNode.EXCLUSIVE_MAXIMUM, false);
+ } catch (Exception e1) {
+ exclusiveMaximum = false;
+ }
+ String valueStr = JSONUtil.getString(valueNode);
+ try {
+ double value = new Double(valueStr).doubleValue();
+ boolean valid = exclusiveMaximum ? value < maximum : value <= maximum;
+ if (!valid) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ if (exclusiveMaximum) {
+ valinfo.addMessage("Value is above the exclusive maximum of " + maximum, line, 0,
+ offset == 0 ? 1 : offset);
+ } else {
+ valinfo.addMessage("Value is above the maximum of " + maximum, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ } catch (NumberFormatException e) {
+ // ignore
+ return;
+ }
+ }
+ }
+
+ private void validateMinimum(IJSONNode node, JsonObject schema, IJSONValue valueNode, JSONValidationInfo valinfo) {
+ double minimum;
+ try {
+ minimum = schema.getDouble(IJSONSchemaNode.MINIMUM, Double.MAX_VALUE);
+ } catch (Exception e) {
+ minimum = Double.MAX_VALUE;
+ }
+ if (minimum < Double.MAX_VALUE) {
+ boolean exclusiveMinimum;
+ try {
+ exclusiveMinimum = schema.getBoolean(IJSONSchemaNode.EXCLUSIVE_MINIMUM, false);
+ } catch (Exception e1) {
+ exclusiveMinimum = false;
+ }
+ String valueStr = JSONUtil.getString(valueNode);
+ try {
+ double value = new Double(valueStr).doubleValue();
+ boolean valid = exclusiveMinimum ? value > minimum : value >= minimum;
+ if (!valid) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ if (exclusiveMinimum) {
+ valinfo.addMessage("Value is below the exclusive minimum of " + minimum, line, 0,
+ offset == 0 ? 1 : offset);
+ } else {
+ valinfo.addMessage("Value is below the minimum of " + minimum, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ } catch (NumberFormatException e) {
+ // ignore
+ return;
+ }
+ }
+ }
+
+ private void validateMultipleOf(IJSONNode node, JsonObject schema, IJSONValue valueNode,
+ JSONValidationInfo valinfo) {
+ int multipleOff;
+ try {
+ multipleOff = schema.getInt(IJSONSchemaNode.MULTIPLEOF, -1);
+ } catch (Exception e) {
+ multipleOff = -1;
+ }
+ if (multipleOff > 0) {
+ String value = JSONUtil.getString(valueNode);
+ double n;
+ try {
+ n = new Double(value).doubleValue();
+ } catch (NumberFormatException e) {
+ // ignore
+ return;
+ }
+ long div = Math.round(n / multipleOff);
+ if (Math.abs(div * multipleOff - n) > 1e-12) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Value is not divisible by " + multipleOff, line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private boolean isType(JSONSchemaType[] types, JSONSchemaType type) {
+ for (JSONSchemaType t : types) {
+ if (t == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void validateString(IJSONNode node, JsonObject schema, Member member, JSONValidationInfo valinfo,
+ IJSONValue value) {
+ if (IJSONSchemaNode.MIN_LENGTH.equals(member.getName())) {
+ validateMinLength(node, schema, value, valinfo);
+ }
+ if (IJSONSchemaNode.MAX_LENGTH.equals(member.getName())) {
+ validateMaxLength(node, schema, value, valinfo);
+ }
+ if (IJSONSchemaNode.PATTERN.equals(member.getName())) {
+ validatePattern(node, schema, value, valinfo);
+ }
+ }
+
+ private void validateMaxLength(IJSONNode node, JsonObject schema, IJSONValue valueNode,
+ JSONValidationInfo valinfo) {
+ int maxLength;
+ try {
+ maxLength = schema.getInt(IJSONSchemaNode.MAX_LENGTH, -1);
+ } catch (Exception e) {
+ maxLength = -1;
+ }
+ if (maxLength >= 0) {
+ String value = JSONUtil.getString(valueNode);
+ boolean valid = value == null || value.length() <= maxLength;
+ if (!valid) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("String is longer than the maximum length of " + maxLength, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private void validateMinLength(IJSONNode node, JsonObject schema, IJSONValue valueNode,
+ JSONValidationInfo valinfo) {
+ int minLength;
+ try {
+ minLength = schema.getInt(IJSONSchemaNode.MIN_LENGTH, -1);
+ } catch (Exception e) {
+ minLength = -1;
+ }
+ if (minLength >= 0) {
+ String value = JSONUtil.getString(valueNode);
+ boolean valid = value == null || value.length() >= minLength;
+ if (!valid) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("String is shorter than the minimum length of " + minLength, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private void validatePattern(IJSONNode node, JsonObject schema, IJSONValue valueNode, JSONValidationInfo valinfo) {
+ String patternStr;
+ try {
+ patternStr = schema.getString(IJSONSchemaNode.PATTERN, null);
+ } catch (Exception e) {
+ patternStr = null;
+ }
+ if (patternStr != null) {
+ String value = JSONUtil.getString(valueNode);
+ if (value != null) {
+ Pattern pattern = Pattern.compile(patternStr);
+ Matcher matcher = pattern.matcher(value);
+ if (!matcher.matches()) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("String does not match the pattern of " + patternStr, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+ }
+
+ private void validateType(IJSONNode node, Member member, JSONValidationInfo valinfo) {
+ if (IJSONSchemaNode.TYPE.equals(member.getName())) {
+ Set<String> types = new HashSet<String>();
+ if (member.getValue().isString()) {
+ types.add(member.getValue().asString());
+ } else if (member.getValue().isArray()) {
+ JsonArray array = (JsonArray) member.getValue();
+ for (JsonValue item : array) {
+ types.add(item.asString());
+ }
+ }
+ boolean valid = false;
+ for (String type : types) {
+ if (node.getNodeType() == IJSONNode.OBJECT_NODE && JSONSchemaType.Object.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (node.getNodeType() == IJSONNode.PAIR_NODE) {
+ IJSONValue value = ((IJSONPair) node).getValue();
+ if (value == null && JSONSchemaType.Null.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value == null) {
+ valid = false;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.OBJECT_NODE && JSONSchemaType.Object.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.VALUE_STRING_NODE
+ && JSONSchemaType.String.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.ARRAY_NODE && JSONSchemaType.Array.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.VALUE_BOOLEAN_NODE
+ && JSONSchemaType.Boolean.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.VALUE_NULL_NODE
+ && JSONSchemaType.Null.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.VALUE_NUMBER_NODE
+ && JSONSchemaType.Number.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ if (value.getNodeType() == IJSONNode.VALUE_NUMBER_NODE
+ && JSONSchemaType.Integer.getName().equals(type)) {
+ valid = true;
+ break;
+ }
+ }
+ }
+ if (!valid) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ StringBuffer buffer = new StringBuffer();
+ Iterator<String> iter = types.iterator();
+ buffer.append(OPEN_BRACKET);
+ while (iter.hasNext()) {
+ buffer.append(iter.next());
+ if (iter.hasNext()) {
+ buffer.append(COMMA);
+ }
+ }
+ buffer.append(CLOSE_BRACKET);
+ valinfo.addMessage("Incorrect type. Expected " + buffer.toString(), line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private void validateEnum(IJSONNode node, JsonObject schema, JSONValidationInfo valinfo) {
+ JsonValue value = schema.get(IJSONSchemaNode.ENUM);
+ if (value instanceof JsonArray) {
+ JsonArray array = value.asArray();
+ Iterator<JsonValue> iter = array.iterator();
+ Set<String> values = new HashSet<String>();
+ while (iter.hasNext()) {
+ String v = iter.next().toString();
+ values.add(JSONUtil.removeQuote(v));
+ }
+ if (node instanceof IJSONPair) {
+ IJSONPair pair = (IJSONPair) node;
+ String v = JSONUtil.getString(pair.getValue());
+ if (!values.contains(v)) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Value is not an accepted value. Valid values " + values + "'", line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+ }
+
+ private void validateRequired(IJSONNode node, JsonObject schema, JSONValidationInfo valinfo) {
+ JsonValue required = schema.get(IJSONSchemaNode.REQUIRED);
+ if (required instanceof JsonArray) {
+ JsonArray array = required.asArray();
+ Iterator<JsonValue> iter = array.iterator();
+ Set<String> values = new HashSet<String>();
+ while (iter.hasNext()) {
+ JsonValue v = iter.next();
+ if (v.isString()) {
+ values.add(v.asString());
+ }
+ }
+ Set<String> properties = getProperties(node);
+ for (String property : properties) {
+ if (property != null && values.contains(property)) {
+ values.remove(property);
+ }
+ }
+ for (String value : values) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Missing property '" + value + "'", line, 0, offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private void validateMinProperties(IJSONNode node, JsonObject schema, JSONValidationInfo valinfo) {
+ int value;
+ try {
+ value = schema.getInt(IJSONSchemaNode.MIN_PROPERTIES, -1);
+ } catch (Exception e) {
+ value = -1;
+ }
+ if (value >= 0) {
+ Set<String> properties = getProperties(node);
+ if (properties.size() < value) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Object has fewer properties than the required number of" + value, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private void validateMaxProperties(IJSONNode node, JsonObject schema, JSONValidationInfo valinfo) {
+ int value;
+ try {
+ value = schema.getInt(IJSONSchemaNode.MAX_PROPERTIES, -1);
+ } catch (Exception e) {
+ value = -1;
+ }
+ if (value >= 0) {
+ Set<String> properties = getProperties(node);
+ if (properties.size() > value) {
+ int offset = node.getStartOffset();
+ int line = node.getModel().getStructuredDocument().getLineOfOffset(offset);
+ valinfo.addMessage("Object has more properties than limit of" + value, line, 0,
+ offset == 0 ? 1 : offset);
+ }
+ }
+ }
+
+ private Set<String> getProperties(IJSONNode node) {
+ Set<String> properties = new HashSet<String>();
+ IJSONNode child = node.getFirstChild();
+ while (child != null) {
+ if (child instanceof IJSONPair) {
+ IJSONPair pair = (IJSONPair) child;
+ if (pair.getName() != null) {
+ properties.add(pair.getName());
+ }
+ }
+ child = child.getNextSibling();
+ }
+ return properties;
+ }
+
+ protected IStructuredModel getModel(String uriString) {
+ URI uri;
+ try {
+ uri = new URI(uriString);
+ } catch (URISyntaxException e) {
+ logWarning(e);
+ return null;
+ }
+ IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(uri);
+ if (files == null || files.length <= 0 || !files[0].exists()) {
+ return null;
+ }
+ IFile file = files[0];
+ IModelManager manager = StructuredModelManager.getModelManager();
+ if (manager == null)
+ return null;
+
+ IStructuredModel model = null;
+ try {
+ file.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
+ } catch (CoreException e) {
+ logWarning(e);
+ }
+ try {
+ try {
+ model = manager.getModelForRead(file);
+ } catch (UnsupportedEncodingException ex) {
+ // retry ignoring META charset for invalid META charset
+ // specification
+ // recreate input stream, because it is already partially read
+ model = manager.getModelForRead(file, new String(), null);
+ }
+ } catch (UnsupportedEncodingException ex) {
+ } catch (IOException ex) {
+ } catch (CoreException e) {
+ logWarning(e);
+ }
+ return model;
+ }
+
+ private static void logWarning(Exception e) {
+ IStatus status = new Status(IStatus.WARNING, JSONCorePlugin.PLUGIN_ID, e.getMessage(), e);
+ JSONCorePlugin.getDefault().getLog().log(status);
+ }
+
/**
* Store additional information in the message parameters. For JSON
* validation there are three additional pieces of information to store:
@@ -131,21 +879,19 @@
* org.eclipse.wst.validation.internal.provisional.core.IMessage)
*/
@Override
- protected void addInfoToMessage(ValidationMessage validationMessage,
- IMessage message) {
+ protected void addInfoToMessage(ValidationMessage validationMessage, IMessage message) {
String key = validationMessage.getKey();
if (key != null) {
JSONMessageInfoHelper messageInfoHelper = new JSONMessageInfoHelper();
- String[] messageInfo = messageInfoHelper.createMessageInfo(key,
- validationMessage.getMessageArguments());
+ String[] messageInfo = messageInfoHelper.createMessageInfo(key, validationMessage.getMessageArguments());
- message.setAttribute(COLUMN_NUMBER_ATTRIBUTE, new Integer(
- validationMessage.getColumnNumber()));
- /*message.setAttribute(SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE,
- messageInfo[0]);
- message.setAttribute(SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE,
- messageInfo[1]);
- */
+ message.setAttribute(COLUMN_NUMBER_ATTRIBUTE, new Integer(validationMessage.getColumnNumber()));
+ /*
+ * message.setAttribute(SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE,
+ * messageInfo[0]);
+ * message.setAttribute(SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE,
+ * messageInfo[1]);
+ */
}
}
@@ -159,8 +905,7 @@
* @return the nested validation context.
*/
@Override
- protected NestedValidatorContext getNestedContext(ValidationState state,
- boolean create) {
+ protected NestedValidatorContext getNestedContext(ValidationState state, boolean create) {
NestedValidatorContext context = null;
Object o = state.get(JSON_VALIDATOR_CONTEXT);
if (o instanceof JSONNestedValidatorContext)
@@ -172,8 +917,7 @@
}
@Override
- public void validationStarting(IProject project, ValidationState state,
- IProgressMonitor monitor) {
+ public void validationStarting(IProject project, ValidationState state, IProgressMonitor monitor) {
if (project != null) {
NestedValidatorContext context = getNestedContext(state, false);
if (context == null) {
@@ -188,8 +932,7 @@
}
@Override
- public void validationFinishing(IProject project, ValidationState state,
- IProgressMonitor monitor) {
+ public void validationFinishing(IProject project, ValidationState state, IProgressMonitor monitor) {
if (project != null) {
super.validationFinishing(project, state, monitor);
NestedValidatorContext context = getNestedContext(state, false);
diff --git a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/preferences/JSONCorePreferenceNames.java b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/preferences/JSONCorePreferenceNames.java
index 79546b5..f3a8db1 100644
--- a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/preferences/JSONCorePreferenceNames.java
+++ b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/preferences/JSONCorePreferenceNames.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 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
@@ -32,6 +32,7 @@
* </p>
*/
public static final String SYNTAX_VALIDATION = "syntaxValidation"; //$NON-NLS-1$
+ public static final String SCHEMA_VALIDATION = "schemaValidation"; //$NON-NLS-1$
/**
* Indicates whether or not a message should be produced when validating a
diff --git a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/util/JSONUtil.java b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/util/JSONUtil.java
index 759a0ba..266a306 100644
--- a/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/util/JSONUtil.java
+++ b/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/util/JSONUtil.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2013-2014 Angelo ZERR.
+ * Copyright (c) 2013-2016 Angelo ZERR.
* 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
@@ -14,6 +14,8 @@
import java.util.Enumeration;
import java.util.Iterator;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.json.core.document.IJSONNode;
import org.eclipse.wst.json.core.internal.Logger;
import org.eclipse.wst.json.core.regions.JSONRegionContexts;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
@@ -23,6 +25,8 @@
public class JSONUtil {
+ public static final String QUOTE = "\""; //$NON-NLS-1$
+
public static void debugOut(String str) {
Logger.log(Logger.WARNING, "json warning: " + str); //$NON-NLS-1$
}
@@ -273,4 +277,29 @@
public static boolean isEndJSONStructure(String regionType) {
return (regionType == JSONRegionContexts.JSON_ARRAY_CLOSE || regionType == JSONRegionContexts.JSON_OBJECT_CLOSE);
}
+
+ public static String getString(IJSONNode node) {
+ String value;
+ try {
+ value = node.getModel().getStructuredDocument().get(node.getStartOffset(), node.getEndOffset()-node.getStartOffset());
+ } catch (BadLocationException e) {
+ // ignore
+ return null;
+ }
+ value = removeQuote(value);
+ return value;
+ }
+
+ public static String removeQuote(String value) {
+ if (value != null) {
+ value = value.trim();
+ if (value.startsWith(QUOTE)) {
+ value = value.substring(1);
+ }
+ if (value.endsWith(QUOTE)) {
+ value = value.substring(0, value.length() - 1);
+ }
+ }
+ return value;
+ }
}
diff --git a/bundles/org.eclipse.wst.json.schemaprocessor/src/org/eclipse/wst/json/schemaprocessor/internal/JSONSchemaProcessor.java b/bundles/org.eclipse.wst.json.schemaprocessor/src/org/eclipse/wst/json/schemaprocessor/internal/JSONSchemaProcessor.java
index 20adfb1..b55ea39 100644
--- a/bundles/org.eclipse.wst.json.schemaprocessor/src/org/eclipse/wst/json/schemaprocessor/internal/JSONSchemaProcessor.java
+++ b/bundles/org.eclipse.wst.json.schemaprocessor/src/org/eclipse/wst/json/schemaprocessor/internal/JSONSchemaProcessor.java
@@ -47,15 +47,21 @@
is = url.openStream();
} else {
File f = HttpClientProvider.getFile(url);
- is = new FileInputStream(f);
+ if (f != null) {
+ is = new FileInputStream(f);
+ }
}
- schemaDocument = new JSONSchemaDocument(new InputStreamReader(is));
+ if (is != null) {
+ schemaDocument = new JSONSchemaDocument(new InputStreamReader(is));
+ }
} finally {
if (is != null) {
is.close();
}
}
- schemaDocuments.put(uriString, schemaDocument);
+ if (schemaDocument != null) {
+ schemaDocuments.put(uriString, schemaDocument);
+ }
return schemaDocument;
}
diff --git a/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.java b/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.java
index c8ab168..8208501 100644
--- a/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.java
+++ b/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.java
@@ -23,6 +23,8 @@
private static final String BUNDLE_NAME = "org.eclipse.wst.json.ui.internal.JSONUIMessages";//$NON-NLS-1$
+ public static String EnableSchemaValidation;
+
public static String Invalid_URL;
public static String The_name_field_is_required;
public static String The_entry_already_exists;
diff --git a/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.properties b/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.properties
index f6ca05f..56d9dbb 100644
--- a/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.properties
+++ b/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/JSONUIMessages.properties
@@ -25,6 +25,7 @@
## Validation preferences page
SyntaxValidation_files=&Enable syntax validation
+EnableSchemaValidation=Enable schema validation
SyntaxValidation_files_label=Errors/Warnings
Severity_error=Error
Severity_warning=Warning
diff --git a/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/preferences/JSONValidatorPreferencePage.java b/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/preferences/JSONValidatorPreferencePage.java
index 9b99574..18855f4 100644
--- a/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/preferences/JSONValidatorPreferencePage.java
+++ b/bundles/org.eclipse.wst.json.ui/src/org/eclipse/wst/json/ui/internal/preferences/JSONValidatorPreferencePage.java
@@ -19,6 +19,7 @@
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.swt.SWT;
@@ -38,6 +39,7 @@
import org.eclipse.wst.json.ui.internal.JSONUIPlugin;
import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractValidationSettingsPage;
+import org.osgi.service.prefs.BackingStoreException;
public class JSONValidatorPreferencePage extends AbstractValidationSettingsPage {
private static final String SETTINGS_SECTION_NAME = "JSONValidationSeverities";//$NON-NLS-1$
@@ -75,6 +77,10 @@
private Group fSyntaxValidationGroup;
private ControlEnableState fSyntaxState;
+ private boolean fOriginalUseSchemaValidation;
+
+ private Button fSchemaValidation;
+
private static final int[] JSON_SEVERITIES = { ValidationMessage.WARNING,
ValidationMessage.ERROR, ValidationMessage.IGNORE };
@@ -122,6 +128,13 @@
}
});
+ fOriginalUseSchemaValidation = getBooleanPreference(
+ JSONCorePreferenceNames.SCHEMA_VALIDATION, false, contexts);
+ fSchemaValidation = createCheckBox(parent,
+ JSONUIMessages.EnableSchemaValidation);
+ ((GridData) fSchemaValidation.getLayoutData()).horizontalSpan = 2;
+ fSchemaValidation
+ .setSelection(fOriginalUseSchemaValidation);
fSyntaxValidationGroup = createGroup(parent, 3);
((GridLayout) fSyntaxValidationGroup.getLayout()).makeColumnsEqualWidth = false;
fSyntaxValidationGroup
@@ -219,6 +232,12 @@
boolean useExtendedSyntaxValidation = modelPreferences.getBoolean(
JSONCorePreferenceNames.SYNTAX_VALIDATION, false);
+ boolean useSchemaValidation = modelPreferences.getBoolean(
+ JSONCorePreferenceNames.SCHEMA_VALIDATION, false);
+ if (fSchemaValidation != null) {
+ fSchemaValidation.setSelection(useSchemaValidation);
+ }
+
if (fExtendedSyntaxValidation != null) {
if (fExtendedSyntaxValidation.getSelection() != useExtendedSyntaxValidation) {
handleSyntaxSeveritySelection(useExtendedSyntaxValidation);
@@ -251,6 +270,11 @@
JSONCorePreferenceNames.SYNTAX_VALIDATION,
extendedSyntaxValidation);
}
+ if (fSchemaValidation != null) {
+ contexts[0].getNode(getPreferenceNodeQualifier()).putBoolean(
+ JSONCorePreferenceNames.SCHEMA_VALIDATION,
+ fSchemaValidation.getSelection());
+ }
}
@Override
@@ -367,8 +391,9 @@
@Override
protected boolean shouldRevalidateOnSettingsChange() {
- return fOriginalUseExtendedSyntaxValidation != fExtendedSyntaxValidation
- .getSelection()
+ return fOriginalUseSchemaValidation != fSchemaValidation.getSelection()
+ || fOriginalUseExtendedSyntaxValidation != fExtendedSyntaxValidation.getSelection()
|| super.shouldRevalidateOnSettingsChange();
}
+
}