| /* |
| * 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.ignite.internal.configuration.hocon; |
| |
| import java.io.Serializable; |
| import java.lang.reflect.Array; |
| import java.util.ArrayDeque; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Deque; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.stream.Collectors; |
| import java.util.stream.IntStream; |
| import java.util.stream.Stream; |
| import com.typesafe.config.ConfigValue; |
| import org.apache.ignite.internal.configuration.tree.ConfigurationVisitor; |
| import org.apache.ignite.internal.configuration.tree.InnerNode; |
| import org.apache.ignite.internal.configuration.tree.NamedListNode; |
| |
| /** |
| * {@link ConfigurationVisitor} implementation that converts a configuration tree to a combination of {@link Map} and |
| * {@link List} objects to convert the result into HOCON {@link ConfigValue} instance. |
| */ |
| class HoconConfigurationVisitor implements ConfigurationVisitor<Object> { |
| /** Stack with intermediate results. Used to store values during recursive calls. */ |
| private Deque<Object> deque = new ArrayDeque<>(); |
| |
| /** {@inheritDoc} */ |
| @Override public Object visitLeafNode(String key, Serializable val) { |
| Object valObj = val; |
| |
| if (val instanceof Character) |
| valObj = val.toString(); |
| else if (val != null && val.getClass().isArray()) |
| valObj = toListOfObjects(val); |
| |
| addToParent(key, valObj); |
| |
| return valObj; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Object visitInnerNode(String key, InnerNode node) { |
| Map<String, Object> innerMap = new HashMap<>(); |
| |
| deque.push(innerMap); |
| |
| node.traverseChildren(this); |
| |
| deque.pop(); |
| |
| addToParent(key, innerMap); |
| |
| return innerMap; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public <N extends InnerNode> Object visitNamedListNode(String key, NamedListNode<N> node) { |
| List<Object> list = new ArrayList<>(node.size()); |
| |
| deque.push(list); |
| |
| for (String subkey : node.namedListKeys()) { |
| node.get(subkey).accept(subkey, this); |
| |
| ((Map<String, Object>)list.get(list.size() - 1)).put(node.syntheticKeyName(), subkey); |
| } |
| |
| deque.pop(); |
| |
| addToParent(key, list); |
| |
| return list; |
| } |
| |
| /** |
| * Adds a sub-element to the parent object if it exists. |
| * |
| * @param key Key for the passed element |
| * @param val Value to add to the parent |
| */ |
| private void addToParent(String key, Object val) { |
| Object parent = deque.peek(); |
| |
| if (parent instanceof Map) |
| ((Map<String, Object>)parent).put(key, val); |
| else if (parent instanceof List) |
| ((Collection<Object>)parent).add(val); |
| } |
| |
| /** |
| * Converts array into a list of objects. Boxes array elements if they are primitive values. |
| * |
| * @param val Array of primitives or array of {@link String}s |
| * @return List of objects corresponding to the passed array. |
| */ |
| private List<?> toListOfObjects(Serializable val) { |
| Stream<?> stream = IntStream.range(0, Array.getLength(val)).mapToObj(i -> Array.get(val, i)); |
| |
| if (val.getClass().getComponentType() == char.class) |
| stream = stream.map(Object::toString); |
| |
| return stream.collect(Collectors.toList()); |
| } |
| } |