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.plugins.context.schema.avro;
23 import java.util.List;
25 import java.util.TreeMap;
27 import org.apache.avro.Schema;
28 import org.onap.policy.apex.context.ContextRuntimeException;
29 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
30 import org.slf4j.ext.XLogger;
31 import org.slf4j.ext.XLoggerFactory;
34 * This class maps between Avro types to Java types. This class is thread safe.
36 * @author Liam Fallon (liam.fallon@ericsson.com)
38 public class AvroObjectMapperFactory {
39 // Get a reference to the logger
40 private static final XLogger LOGGER = XLoggerFactory.getXLogger(AvroObjectMapperFactory.class);
42 // Map for Avro primitive types to Java primitive types
43 private static final Map<Schema.Type, Class<? extends AvroObjectMapper>> AVRO_OBJECT_MAPPER_MAP = new TreeMap<>();
46 // Initialize the mapping
48 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.ARRAY, AvroArrayObjectMapper.class);
49 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.BOOLEAN, AvroDirectObjectMapper.class);
50 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.BYTES, AvroBytesObjectMapper.class);
51 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.DOUBLE, AvroDirectObjectMapper.class);
52 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.ENUM, AvroEnumObjectMapper.class);
53 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.FIXED, AvroDirectObjectMapper.class);
54 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.FLOAT, AvroDirectObjectMapper.class);
55 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.INT, AvroDirectObjectMapper.class);
56 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.LONG, AvroDirectObjectMapper.class);
57 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.MAP, AvroDirectObjectMapper.class);
58 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.NULL, AvroDirectObjectMapper.class);
59 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.RECORD, AvroRecordObjectMapper.class);
60 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.STRING, AvroStringObjectMapper.class);
61 AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.UNION, null);
66 * Gets the Avro object mapper to use for an artifact with the given key and schema.
68 * @param userKey the key of the artifact
69 * @param incomingSchema the incoming schema
70 * @return the avro object mapper
72 public AvroObjectMapper get(final AxKey userKey, final Schema incomingSchema) {
73 Schema schema = incomingSchema;
74 boolean isnullable = false;
75 if (Schema.Type.UNION.equals(schema.getType())) {
77 final List<Schema> types = schema.getTypes();
79 // currently only support unions with 2 types, one of which is NULL
80 final Schema nullschema = Schema.create(Schema.Type.NULL);
81 if (types.size() != 2 || !types.contains(nullschema)) {
82 final String resultSting = userKey.getId()
83 + ": Apex currently only supports UNION schemas with 2 options, one must be NULL";
84 LOGGER.warn(resultSting);
85 throw new ContextRuntimeException(resultSting);
88 // get the non-null schema given for the union so it can be wrapped
89 schema = types.get(0);
90 if (Schema.Type.NULL.equals(schema.getType())) {
91 schema = types.get(1);
93 if (Schema.Type.NULL.equals(schema.getType())) {
94 final String resultSting = userKey.getId()
95 + ": Apex currently only supports UNION schema2 with 2 options, "
96 + "only one can be NULL, and the other cannot be another UNION";
97 LOGGER.warn(resultSting);
98 throw new ContextRuntimeException(resultSting);
102 final Schema.Type avroType = schema.getType();
104 // Check that there is a definition for the mapper for this type
105 if (!AVRO_OBJECT_MAPPER_MAP.containsKey(avroType) || AVRO_OBJECT_MAPPER_MAP.get(avroType) == null) {
106 final String resultSting = userKey.getId() + ": no Avro object mapper defined for Avro type \"" + avroType
108 LOGGER.warn(resultSting);
109 throw new ContextRuntimeException(resultSting);
113 AvroObjectMapper avroObjectMapper;
115 avroObjectMapper = AVRO_OBJECT_MAPPER_MAP.get(avroType).newInstance();
117 avroObjectMapper = new AvroNullableMapper(avroObjectMapper);
120 } catch (final Exception e) {
121 final String resultSting = userKey.getId() + ": could not create an Avro object mapper of type \""
122 + AVRO_OBJECT_MAPPER_MAP.get(avroType) + "\" for Avro type \"" + avroType + "\" : " + e;
123 LOGGER.warn(resultSting, e);
124 throw new ContextRuntimeException(resultSting, e);
127 // Set the type and return
128 avroObjectMapper.init(userKey, avroType);
130 return avroObjectMapper;