Skip to content

Commit 96e08bb

Browse files
committed
#68 editor supports formats, schema injection, editor supports ace
1 parent b6168ba commit 96e08bb

File tree

5 files changed

+94
-15
lines changed

5 files changed

+94
-15
lines changed

jackson/src/main/java/eu/mihosoft/vmf/jackson/VMFJsonSchemaGenerator.java

+44-12
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ private void addDefaultValueAndDescriptionAndConstraintIfAvailable(Property prop
446446
addFormat(property, propertySchema);
447447
addUniqueItems(property, propertySchema);
448448
addInjections(property, propertySchema);
449+
addTitle(property, propertySchema);
450+
addPropertyOrder(property, propertySchema);
449451
}
450452

451453
private void addDefaultValue(Property property, Map<String, Object> propertySchema) {
@@ -523,27 +525,31 @@ private void addConstraint(Property property, Map<String, Object> propertySchema
523525

524526
private void addUniqueItems(Property property, Map<String, Object> propertySchema) {
525527
try {
526-
var uniqueItems = property.annotationByKey("vmf:jackson:schema:uniqueItems").get().getValue();
527-
if (uniqueItems != null) {
528-
propertySchema.put("uniqueItems", Boolean.parseBoolean(uniqueItems));
528+
var uniqueItemsOpt = property.annotationByKey("vmf:jackson:schema:uniqueItems");
529+
if (uniqueItemsOpt.isPresent() && uniqueItemsOpt.get().getValue() != null) {
530+
var uniqueItems = uniqueItemsOpt.get().getValue();
531+
if (uniqueItems != null) {
532+
propertySchema.put("uniqueItems", Boolean.parseBoolean(uniqueItems));
533+
}
529534
}
530535
} catch (Exception e) {
531-
// ignore, not possible to get default value
536+
throw new RuntimeException("Failed to parse uniqueItems", e);
532537
}
533538
}
534539

535540
private void addInjections(Property property, Map<String, Object> propertySchema) {
536541
try {
537-
var injections = property.annotationByKey("vmf:jackson:schema:inject").get().getValue();
538-
if (injections != null) {
539-
System.out.println("!!!injections: " + injections);
540-
// inject json into schema by parsing it and adding it to the schema
541-
var injectionsMap = new ObjectMapper().readValue("{"+injections+"}", Map.class);
542-
propertySchema.putAll(injectionsMap);
542+
var injectionsOpt = property.annotationByKey("vmf:jackson:schema:inject");
543+
if (injectionsOpt.isPresent() && injectionsOpt.get().getValue() != null) {
544+
var injections = injectionsOpt.get().getValue();
545+
if (injections != null) {
546+
// inject json into schema by parsing it and adding it to the schema
547+
var injectionsMap = new ObjectMapper().readValue("{" + injections + "}", Map.class);
548+
propertySchema.putAll(injectionsMap);
549+
}
543550
}
544551
} catch (Exception e) {
545-
// ignore, not possible to get default value
546-
e.printStackTrace();
552+
throw new RuntimeException("Failed to parse injection JSON", e);
547553
}
548554
}
549555

@@ -557,4 +563,30 @@ private void addFormat(Property property, Map<String, Object> propertySchema) {
557563
// ignore, not possible to get default value
558564
}
559565
}
566+
567+
private void addTitle(Property property, Map<String, Object> propertySchema) {
568+
try {
569+
var title = property.annotationByKey("vmf:jackson:schema:title").get().getValue();
570+
if (title != null) {
571+
propertySchema.put("title", title);
572+
}
573+
} catch (Exception e) {
574+
// ignore, not possible to get default value
575+
}
576+
}
577+
578+
private void addPropertyOrder(Property property, Map<String, Object> propertySchema) {
579+
// order is an integer value that specifies the order of the property in the schema
580+
try {
581+
var orderOpt = property.annotationByKey("vmf:jackson:schema:propertyOrder");
582+
if (orderOpt.isPresent() && orderOpt.get().getValue() != null) {
583+
var order = orderOpt.get().getValue();
584+
if (order != null) {
585+
propertySchema.put("propertyOrder", Integer.parseInt(order));
586+
}
587+
}
588+
} catch (Exception e) {
589+
throw new RuntimeException("Failed to parse property order", e);
590+
}
591+
}
560592
}

jackson/src/test/vmf/eu/mihosoft/vmf/jackson/test/type_formats01/vmfmodel/FormatModel01.java

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ interface Pet {
2727

2828
@Annotation(key = "vmf:jackson:schema:inject", value = "\"title\": \"My Title\"")
2929
String getOtherProperty();
30+
31+
@Contains(opposite = "owner")
32+
@Annotation(key= "vmf:jackson:schema:format", value = "table")
33+
Prop[] getProperties();
34+
}
35+
36+
interface Prop {
37+
String getKey();
38+
String getValue();
39+
@Container(opposite = "properties")
40+
Pet getOwner();
3041
}
3142

3243

vmfedit/build.gradle

+15-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ task installJsonEditor(type: NpmTask) {
105105

106106
task copyJsonEditorToResources(type: Copy) {
107107
from 'node_modules/@json-editor/json-editor/dist'
108-
into 'src/main/resources/json-editor'
108+
// into 'src/main/resources/json-editor'
109+
into 'src/main/resources/eu/mihosoft/vmf/vmfedit/json-editor'
109110
include '**/*'
110111
}
111112

@@ -150,6 +151,16 @@ task copyJSON5ToResources(type: Copy) {
150151
include '**/*'
151152
}
152153

154+
task installACEEditor(type: NpmTask) {
155+
args = ['install', '[email protected]']
156+
}
157+
158+
task copyACEEditorToResources(type: Copy) {
159+
from 'node_modules/ace-builds/src-min-noconflict'
160+
into 'src/main/resources/eu/mihosoft/vmf/vmfedit/ace-builds'
161+
include '**/*'
162+
}
163+
153164
copyJsonEditorToResources.dependsOn installJsonEditor
154165
processResources.dependsOn copyJsonEditorToResources
155166

@@ -165,6 +176,9 @@ processResources.dependsOn copyBootStrapToResources
165176
copySpectreToResources.dependsOn installSpectre
166177
processResources.dependsOn copySpectreToResources
167178

179+
copyACEEditorToResources.dependsOn installACEEditor
180+
processResources.dependsOn copyACEEditorToResources
181+
168182

169183

170184
jar {

vmfedit/src/main/java/eu/mihosoft/vmf/vmfedit/JsonEditorController.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import netscape.javascript.JSObject;
1212

1313
import java.net.URL;
14+
import java.util.Objects;
1415
import java.util.concurrent.CompletableFuture;
1516
import java.util.function.BiConsumer;
1617
import java.util.function.Consumer;
@@ -28,6 +29,8 @@ public class JsonEditorController {
2829
/** The WebView component used to display the JSON editor */
2930
private final WebView webView;
3031

32+
private volatile boolean updatingValue = false;
33+
3134
/** Property holding the current JSON schema */
3235
private final StringProperty schemaProperty = new SimpleStringProperty(
3336
"{\n" +
@@ -142,7 +145,12 @@ public MyEditorCallback(JsonEditorController control) {
142145
public void accept(String newValue) {
143146
new Thread(() -> {
144147
Platform.runLater(() -> {
145-
control.valueProperty().set(newValue);
148+
control.updatingValue = true;
149+
try {
150+
control.valueProperty().set(newValue);
151+
} finally {
152+
control.updatingValue = false;
153+
}
146154
});
147155
}).start();
148156
}
@@ -284,6 +292,11 @@ private void handleSchemaUpdate(String schema) {
284292
* Attempts to migrate an existing value to a new schema.
285293
*/
286294
private void attemptValueMigration(String value) {
295+
296+
if(updatingValue) {
297+
return;
298+
}
299+
287300
Thread.ofVirtual().start(() -> {
288301
for (int i = 0; i < 10; i++) {
289302
if (trySetValue(value)) break;
@@ -300,6 +313,9 @@ private void attemptValueMigration(String value) {
300313
* Attempts to set a value in the editor with proper UI thread handling.
301314
*/
302315
private boolean trySetValue(String value) {
316+
if(updatingValue) {
317+
return true;
318+
}
303319
var future = new CompletableFuture<Boolean>();
304320
Platform.runLater(() -> {
305321
try {

vmfedit/src/main/resources/eu/mihosoft/vmf/vmfedit/json-editor.html

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
1010
<link rel="stylesheet" href="fontawesome-free/css/all.min.css">
1111
<title>JSON Editor</title>
12-
<script src="../../../../json-editor/jsoneditor.js"></script>
12+
<script src="json-editor/jsoneditor.js"></script>
13+
<script src="ace-builds/ace.js"></script>
1314
<style>
1415
body { margin: 0; padding: 0; }
1516
#editor_holder { width: 100%; height: 100vh; }
@@ -20,6 +21,9 @@
2021
<div id="editor_holder"></div>
2122
<script>
2223

24+
// Set ACE Editor basePath to path
25+
window.ace.config.set("basePath", "ace-builds/");
26+
2327
// At the top of your script section, before any other code
2428
const EditorCallbacks = {
2529
timestamp: new Date().toLocaleTimeString(),
@@ -55,6 +59,7 @@
5559
// };
5660

5761
function initEditor(schema) {
62+
5863
console.log("Initializing editor with schema:", schema);
5964
if (editor) {
6065
currentValue = editor.getValue();
@@ -100,6 +105,7 @@
100105

101106
window.onload = function() {
102107
console.log("Window loaded");
108+
103109
initEditor({});
104110
};
105111

0 commit comments

Comments
 (0)