2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.apex.context.impl.schema.java;
23 import com.google.gson.Gson;
24 import com.google.gson.JsonElement;
26 import java.lang.reflect.Constructor;
27 import java.util.HashMap;
30 import org.onap.policy.apex.context.ContextRuntimeException;
31 import org.onap.policy.apex.context.impl.schema.AbstractSchemaHelper;
32 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
33 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
34 import org.onap.policy.apex.model.utilities.typeutils.TypeBuilder;
35 import org.slf4j.ext.XLogger;
36 import org.slf4j.ext.XLoggerFactory;
39 * This class implements translation to and from Apex distributed objects and Java objects when a Java schema is used.
40 * It creates schema items as Java objects and marshals and unmarshals these objects in various formats. All objects
41 * must be of the type of Java class defined in the schema.
43 * @author Liam Fallon (liam.fallon@ericsson.com)
45 public class JavaSchemaHelper extends AbstractSchemaHelper {
46 // Get a reference to the logger
47 private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavaSchemaHelper.class);
49 // This map defines the built in types in types in Java
51 private static final Map<String, Class<?>> BUILT_IN_MAP = new HashMap<>();
53 BUILT_IN_MAP.put("int", Integer .TYPE);
54 BUILT_IN_MAP.put("long", Long .TYPE);
55 BUILT_IN_MAP.put("double", Double .TYPE);
56 BUILT_IN_MAP.put("float", Float .TYPE);
57 BUILT_IN_MAP.put("bool", Boolean .TYPE);
58 BUILT_IN_MAP.put("char", Character.TYPE);
59 BUILT_IN_MAP.put("byte", Byte .TYPE);
60 BUILT_IN_MAP.put("void", Void .TYPE);
61 BUILT_IN_MAP.put("short", Short .TYPE);
68 * @see org.onap.policy.apex.context.impl.schema.AbstractSchemaHelper#init(org.onap.policy.apex.model.basicmodel.
69 * concepts. AxKey, org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema)
72 public void init(final AxKey userKey, final AxContextSchema schema) throws ContextRuntimeException {
73 super.init(userKey, schema);
75 final String javatype = schema.getSchema();
76 // For Java, the schema is the Java class canonical path
79 setSchemaClass(TypeBuilder.getJavaTypeClass(schema.getSchema()));
80 } catch (final IllegalArgumentException e) {
82 String resultSting = userKey.getID() + ": class/type " + schema.getSchema() + " for context schema \""
83 + schema.getID() + "\" not found.";
84 if (JavaSchemaHelper.BUILT_IN_MAP.get(javatype) != null) {
85 resultSting += " Primitive types are not supported. Use the appropriate Java boxing type instead.";
87 resultSting += " Check the class path of the JVM";
89 LOGGER.warn(resultSting);
90 throw new ContextRuntimeException(resultSting, e);
97 * @see org.onap.policy.apex.context.SchemaHelper#createNewInstance(com.google.gson.JsonElement)
100 public Object createNewInstance(final JsonElement jsonElement) {
101 final String elementJsonString = new Gson().toJson(jsonElement);
103 return new Gson().fromJson(elementJsonString, this.getSchemaClass());
109 * @see org.onap.policy.apex.context.SchemaHelper#object2SchemaObject(java.lang.Object)
112 public Object unmarshal(final Object object) {
113 if (object == null) {
117 // If the object is an instance of the incoming object, carry on
118 if (object.getClass().equals(getSchemaClass())) {
122 // For numeric types, do a numeric conversion
123 if (Number.class.isAssignableFrom(getSchemaClass())) {
124 return numericConversion(object);
127 if (getSchemaClass().isAssignableFrom(object.getClass())) {
130 return stringConversion(object);
137 * @see org.onap.policy.apex.context.SchemaHelper#schemaObject2Json(java.lang.Object)
140 public String marshal2Json(final Object schemaObject) {
141 if (schemaObject == null) {
145 // Check the incoming object is of a correct class
146 if (getSchemaClass().isAssignableFrom(schemaObject.getClass())) {
147 // Use Gson to translate the object
148 return new Gson().toJson(schemaObject);
150 final String returnString = getUserKey().getID() + ": object \"" + schemaObject.toString()
151 + "\" of class \"" + schemaObject.getClass().getCanonicalName() + "\" not compatible with class \""
152 + getSchemaClass().getCanonicalName() + "\"";
153 LOGGER.warn(returnString);
154 throw new ContextRuntimeException(returnString);
161 * @see org.onap.policy.apex.context.SchemaHelper#marshal2JsonElement(java.lang.Object)
164 public JsonElement marshal2JsonElement(final Object schemaObject) {
165 // Use Gson to marshal the schema object into a Json element to return
166 return new Gson().toJsonTree(schemaObject, getSchemaClass());
170 * Do a numeric conversion between numeric types.
172 * @param object The incoming numeric object
173 * @return The converted object
175 private Object numericConversion(final Object object) {
176 // Check if the incoming object is a number, if not do a string conversion
177 if (object instanceof Number) {
178 if (getSchemaClass().isAssignableFrom(Byte.class)) {
179 return ((Number) object).byteValue();
180 } else if (getSchemaClass().isAssignableFrom(Integer.class)) {
181 return ((Number) object).intValue();
182 } else if (getSchemaClass().isAssignableFrom(Long.class)) {
183 return ((Number) object).longValue();
184 } else if (getSchemaClass().isAssignableFrom(Float.class)) {
185 return ((Number) object).floatValue();
186 } else if (getSchemaClass().isAssignableFrom(Double.class)) {
187 return ((Number) object).doubleValue();
191 // OK, we'll try and convert from a string representation of the incoming object
192 return stringConversion(object);
196 * Do a string conversion to the class type.
198 * @param object The incoming numeric object
199 * @return The converted object
201 private Object stringConversion(final Object object) {
202 // OK, we'll try and convert from a string representation of the incoming object
204 final Constructor<?> stringConstructor = getSchemaClass().getConstructor(String.class);
205 return stringConstructor.newInstance(object.toString());
206 } catch (final Exception e) {
207 final String returnString = getUserKey().getID() + ": object \"" + object.toString() + "\" of class \""
208 + object.getClass().getCanonicalName() + "\" not compatible with class \""
209 + getSchemaClass().getCanonicalName() + "\"";
210 LOGGER.warn(returnString);
211 throw new ContextRuntimeException(returnString);