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  
31  public final class MetadataUtils {
32    private MetadataUtils() {
33      // disable construction
34    }
35  
36    public static void generateTitle(@NonNull INamedModelElement named, @NonNull ObjectNode obj) {
37      String formalName = named.getEffectiveFormalName();
38      if (formalName != null) {
39        obj.put("title", formalName);
40      }
41    }
42  
43    public static <NAMED extends INamedModelElement & IModelElement> void generateDescription(@NonNull NAMED named,
44        @NonNull ObjectNode obj) {
45      MarkupLine description = named.getEffectiveDescription();
46  
47      StringBuilder retval = null;
48      if (description != null) {
49        retval = new StringBuilder().append(description.toMarkdown());
50      }
51  
52      MarkupMultiline remarks = named.getRemarks();
53      if (remarks != null) {
54        if (retval == null) {
55          retval = new StringBuilder();
56        } else {
57          retval.append("\n\n");
58        }
59        retval.append(remarks.toMarkdown());
60      }
61      if (retval != null) {
62        obj.put("description", retval.toString());
63      }
64    }
65  
66    public static void generateDefault(IValuedInstance instance, ObjectNode obj) {
67      Object defaultValue = instance.getEffectiveDefaultValue();
68      if (defaultValue != null) {
69        IValuedDefinition definition = instance.getDefinition();
70        IDataTypeAdapter<?> adapter = definition.getJavaTypeAdapter();
71        obj.set("default", toJsonValue(defaultValue, adapter));
72      }
73    }
74  
75    private static JsonNode toJsonValue(Object defaultValue, IDataTypeAdapter<?> adapter) {
76      JsonNode retval = null;
77      switch (adapter.getJsonRawType()) {
78      case BOOLEAN:
79        if (defaultValue instanceof Boolean) {
80          retval = BooleanNode.valueOf((Boolean) defaultValue);
81        } // else use default conversion
82        break;
83      case INTEGER:
84        if (defaultValue instanceof BigInteger) {
85          retval = BigIntegerNode.valueOf((BigInteger) defaultValue);
86        } else if (defaultValue instanceof Integer) {
87          retval = IntNode.valueOf((Integer) defaultValue);
88        } else if (defaultValue instanceof Long) {
89          retval = LongNode.valueOf((Long) defaultValue);
90        } // else use default conversion
91        break;
92      case NUMBER:
93        if (defaultValue instanceof BigDecimal) {
94          retval = DecimalNode.valueOf((BigDecimal) defaultValue);
95        } else if (defaultValue instanceof Double) {
96          retval = DoubleNode.valueOf((Double) defaultValue);
97        } // else use default conversion
98        break;
99      case ANY:
100     case ARRAY:
101     case OBJECT:
102     case NULL:
103       throw new UnsupportedOperationException("Invalid type: " + defaultValue.getClass());
104     case STRING:
105     default:
106       // use default conversion
107       break;
108     }
109 
110     if (retval == null) {
111       retval = TextNode.valueOf(adapter.asString(defaultValue));
112     }
113     return retval;
114   }
115 }