1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.schemagen.json.impl;
7   
8   import com.fasterxml.jackson.databind.JsonNode;
9   import com.fasterxml.jackson.databind.node.BigIntegerNode;
10  import com.fasterxml.jackson.databind.node.BooleanNode;
11  import com.fasterxml.jackson.databind.node.DecimalNode;
12  import com.fasterxml.jackson.databind.node.DoubleNode;
13  import com.fasterxml.jackson.databind.node.IntNode;
14  import com.fasterxml.jackson.databind.node.LongNode;
15  import com.fasterxml.jackson.databind.node.ObjectNode;
16  import com.fasterxml.jackson.databind.node.TextNode;
17  
18  import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
19  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
20  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
21  import gov.nist.secauto.metaschema.core.model.IModelElement;
22  import gov.nist.secauto.metaschema.core.model.INamedModelElement;
23  import gov.nist.secauto.metaschema.core.model.IValuedDefinition;
24  import gov.nist.secauto.metaschema.core.model.IValuedInstance;
25  
26  import java.math.BigDecimal;
27  import java.math.BigInteger;
28  
29  import edu.umd.cs.findbugs.annotations.NonNull;
30  import edu.umd.cs.findbugs.annotations.Nullable;
31  
32  public final class MetadataUtils {
33    private MetadataUtils() {
34      // disable construction
35    }
36  
37    public static void generateTitle(@NonNull INamedModelElement named, @NonNull ObjectNode obj) {
38      String formalName = named.getEffectiveFormalName();
39      if (formalName != null) {
40        obj.put("title", formalName);
41      }
42    }
43  
44    public static <NAMED extends INamedModelElement & IModelElement> void generateDescription(@NonNull NAMED named,
45        @NonNull ObjectNode obj) {
46      MarkupLine description = named.getEffectiveDescription();
47  
48      StringBuilder retval = null;
49      if (description != null) {
50        retval = new StringBuilder().append(description.toMarkdown());
51      }
52  
53      MarkupMultiline remarks = named.getRemarks();
54      if (remarks != null) {
55        if (retval == null) {
56          retval = new StringBuilder();
57        } else {
58          retval.append("\n\n");
59        }
60        retval.append(remarks.toMarkdown());
61      }
62      if (retval != null) {
63        obj.put("description", retval.toString());
64      }
65    }
66  
67    public static void generateDefault(IValuedInstance instance, ObjectNode obj) {
68      Object defaultValue = instance.getEffectiveDefaultValue();
69      if (defaultValue != null) {
70        IValuedDefinition definition = instance.getDefinition();
71        IDataTypeAdapter<?> adapter = definition.getJavaTypeAdapter();
72        obj.set("default", toJsonValue(defaultValue, adapter));
73      }
74    }
75  
76    private static JsonNode toJsonValue(@Nullable Object defaultValue, @NonNull IDataTypeAdapter<?> adapter) {
77      JsonNode retval = null;
78      switch (adapter.getJsonRawType()) {
79      case BOOLEAN:
80        if (defaultValue instanceof Boolean) {
81          retval = BooleanNode.valueOf((Boolean) defaultValue);
82        } // else use default conversion
83        break;
84      case INTEGER:
85        if (defaultValue instanceof BigInteger) {
86          retval = BigIntegerNode.valueOf((BigInteger) defaultValue);
87        } else if (defaultValue instanceof Integer) {
88          retval = IntNode.valueOf((Integer) defaultValue);
89        } else if (defaultValue instanceof Long) {
90          retval = LongNode.valueOf((Long) defaultValue);
91        } // else use default conversion
92        break;
93      case NUMBER:
94        if (defaultValue instanceof BigDecimal) {
95          retval = DecimalNode.valueOf((BigDecimal) defaultValue);
96        } else if (defaultValue instanceof Double) {
97          retval = DoubleNode.valueOf((Double) defaultValue);
98        } // else use default conversion
99        break;
100     case ANY:
101     case ARRAY:
102     case OBJECT:
103     case NULL:
104       throw new UnsupportedOperationException("Invalid type: " + adapter.getClass());
105     case STRING:
106     default:
107       // use default conversion
108       break;
109     }
110 
111     if (retval == null && defaultValue != null) {
112       retval = TextNode.valueOf(adapter.asString(defaultValue));
113     }
114     return retval;
115   }
116 }