| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.felix.dm.annotation.plugin.bnd; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import aQute.bnd.osgi.Annotation; |
| |
| /** |
| * This class encodes a component descriptor entry line, using json. |
| * We are using a slightly adapted version of the nice JsonSerializingImpl class from the Apache Felix Converter project. |
| * |
| * Internally, we store parameters in a map. The format of key/values stored in the map is the following: |
| * |
| * The JSON object has the following form: |
| * |
| * entry ::= String | String[] | dictionary |
| * dictionary ::= key-value-pair* |
| * key-value-pair ::= key value |
| * value ::= String | String[] | value-type |
| * value-type ::= jsonObject with value-type-info |
| * value-type-info ::= "type"=primitive java type |
| * "value"=String|String[] |
| * |
| * Exemple: |
| * |
| * {"string-param" : "string-value", |
| * "string-array-param" : ["string1", "string2"], |
| * "properties" : { |
| * "string-param" : "string-value", |
| * "string-array-param" : ["str1", "str2], |
| * "long-param" : {"type":"java.lang.Long", "value":"1"}} |
| * "long-array-param" : {"type":"java.lang.Long", "value":["1"]}} |
| * } |
| * } |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public class EntryWriter |
| { |
| /** |
| * Every descriptor entries contains a type parameter for identifying the kind of entry |
| */ |
| private final static String TYPE = "type"; |
| |
| /** |
| * All parameters as stored in a map object |
| */ |
| private final HashMap<String, Object> m_params = new HashMap<>(); |
| |
| /** The entry type */ |
| private final EntryType m_type; |
| |
| /** |
| * Makes a new component descriptor entry. |
| */ |
| public EntryWriter(EntryType type) |
| { |
| m_type = type; |
| m_params.put("type", type.toString()); |
| } |
| |
| /** |
| * Returns this entry type. |
| */ |
| EntryType getEntryType() |
| { |
| return m_type; |
| } |
| |
| /** |
| * Returns a string representation for the given component descriptor entry. |
| * @param m_logger |
| */ |
| public String toString() |
| { |
| return new JsonWriter(m_params).toString(); |
| } |
| |
| /** |
| * Adds a String parameter in this descritor entry. |
| */ |
| public void put(EntryParam param, String value) |
| { |
| checkType(param.toString()); |
| m_params.put(param.toString(), value); |
| } |
| |
| /** |
| * Adds a String[] parameter in this descriptor entry. |
| */ |
| public void put(EntryParam param, String[] values) |
| { |
| checkType(param.toString()); |
| m_params.put(param.toString(), Arrays.asList(values)); |
| } |
| |
| /** |
| * Adds a property in this descriptor entry. |
| */ |
| @SuppressWarnings("unchecked") |
| public void addProperty(String name, Object value, Class<?> type) |
| { |
| Map<String, Object> properties = (Map<String, Object>) m_params.get(EntryParam.properties.toString()); |
| if (properties == null) { |
| properties = new HashMap<>(); |
| m_params.put(EntryParam.properties.toString(), properties); |
| } |
| if (value.getClass().isArray()) |
| { |
| Object[] array = (Object[]) value; |
| if (array.length == 1) |
| { |
| value = array[0]; |
| } |
| } |
| |
| if (type.equals(String.class)) |
| { |
| properties.put(name, value.getClass().isArray() ? Arrays.asList((Object[]) value) : value); |
| } |
| else |
| { |
| Map<String, Object> val = new HashMap<>(); |
| val.put("type", type.getName()); |
| val.put("value", value.getClass().isArray() ? Arrays.asList((Object[]) value) : value); |
| properties.put(name, val); |
| } |
| } |
| |
| /** |
| * Get a String attribute value from an annotation and write it into this descriptor entry. |
| */ |
| public String putString(Annotation annotation, EntryParam param, String def) |
| { |
| checkType(param.toString()); |
| Object value = annotation.get(param.toString()); |
| if (value == null && def != null) |
| { |
| value = def; |
| } |
| if (value != null) |
| { |
| put(param, value.toString()); |
| } |
| return value == null ? null : value.toString(); |
| } |
| |
| /** |
| * Get a class attribute value from an annotation and write it into this descriptor entry. |
| */ |
| public void putClass(Annotation annotation, EntryParam param) |
| { |
| checkType(param.toString()); |
| String value = AnnotationCollector.parseClassAttrValue(annotation.get(param.toString())); |
| if (value != null) |
| { |
| put(param, value); |
| } |
| } |
| |
| /** |
| * Get a class array attribute value from an annotation and write it into this descriptor entry. |
| * |
| * @param annotation the annotation containing an array of classes |
| * @param param the attribute name corresponding to an array of classes |
| * @param def the default array of classes (String[]), if the attribute is not defined in the annotation |
| * @return the class array size. |
| */ |
| public int putClassArray(Annotation annotation, EntryParam param, Object def, Set<String> collect) |
| { |
| checkType(param.toString()); |
| |
| boolean usingDefault = false; |
| Object value = annotation.get(param.toString()); |
| if (value == null && def != null) |
| { |
| value = def; |
| usingDefault = true; |
| } |
| if (value != null) |
| { |
| if (!(value instanceof Object[])) |
| { |
| throw new IllegalArgumentException("annotation parameter " + param |
| + " has not a class array type"); |
| } |
| |
| List<String> classes = new ArrayList<>(); |
| for (Object v: ((Object[]) value)) |
| { |
| if (! usingDefault) |
| { |
| // Parse the annotation attribute value. |
| v = AnnotationCollector.parseClassAttrValue(v); |
| } |
| classes.add(v.toString()); |
| collect.add(v.toString()); |
| } |
| |
| m_params.put(param.toString(), classes); |
| return ((Object[]) value).length; |
| } |
| return 0; |
| } |
| |
| /** |
| * Check if the written key is not equals to "type" ("type" is an internal attribute we are using |
| * in order to identify a kind of descriptor entry (Service, ServiceDependency, etc ...). |
| */ |
| private void checkType(String key) |
| { |
| if (TYPE.equals(key)) |
| { |
| throw new IllegalArgumentException("\"" + TYPE + "\" parameter can't be overriden"); |
| } |
| } |
| } |