org.snakeyaml.engine.v2.representer.StandardRepresenter Maven / Gradle / Ivy
Show all versions of snakeyaml-engine Show documentation
/**
* Copyright (c) 2018, http://www.snakeyaml.org
*
* Licensed 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.snakeyaml.engine.v2.representer;
import org.snakeyaml.engine.v2.api.DumpSettings;
import org.snakeyaml.engine.v2.api.RepresentToNode;
import org.snakeyaml.engine.v2.common.FlowStyle;
import org.snakeyaml.engine.v2.common.NonPrintableStyle;
import org.snakeyaml.engine.v2.common.ScalarStyle;
import org.snakeyaml.engine.v2.exceptions.YamlEngineException;
import org.snakeyaml.engine.v2.nodes.Node;
import org.snakeyaml.engine.v2.nodes.Tag;
import org.snakeyaml.engine.v2.scanner.StreamReader;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
/**
* Represent standard Java classes
*/
public class StandardRepresenter extends BaseRepresenter {
protected Map, Tag> classTags;
protected DumpSettings settings;
public StandardRepresenter(DumpSettings settings) {
this.defaultFlowStyle = settings.getDefaultFlowStyle();
this.defaultScalarStyle = settings.getDefaultScalarStyle();
this.nullRepresenter = new RepresentNull();
this.representers.put(String.class, new RepresentString());
this.representers.put(Boolean.class, new RepresentBoolean());
this.representers.put(Character.class, new RepresentString());
this.representers.put(UUID.class, new RepresentUuid());
this.representers.put(Optional.class, new RepresentOptional());
this.representers.put(byte[].class, new RepresentByteArray());
RepresentToNode primitiveArray = new RepresentPrimitiveArray();
representers.put(short[].class, primitiveArray);
representers.put(int[].class, primitiveArray);
representers.put(long[].class, primitiveArray);
representers.put(float[].class, primitiveArray);
representers.put(double[].class, primitiveArray);
representers.put(char[].class, primitiveArray);
representers.put(boolean[].class, primitiveArray);
this.parentClassRepresenters.put(Number.class, new RepresentNumber());
this.parentClassRepresenters.put(List.class, new RepresentList());
this.parentClassRepresenters.put(Map.class, new RepresentMap());
this.parentClassRepresenters.put(Set.class, new RepresentSet());
this.parentClassRepresenters.put(Iterator.class, new RepresentIterator());
this.parentClassRepresenters.put(new Object[0].getClass(), new RepresentArray());
this.parentClassRepresenters.put(Enum.class, new RepresentEnum());
classTags = new HashMap();
this.settings = settings;
}
protected Tag getTag(Class> clazz, Tag defaultTag) {
if (classTags.containsKey(clazz)) {
return classTags.get(clazz);
} else {
return defaultTag;
}
}
/**
* Define a tag for the Class
to serialize.
*
* @param clazz Class
which tag is changed
* @param tag new tag to be used for every instance of the specified
* Class
* @return the previous tag associated with the Class
*/
public Tag addClassTag(Class extends Object> clazz, Tag tag) {
if (tag == null) {
throw new NullPointerException("Tag must be provided.");
}
return classTags.put(clazz, tag);
}
//remove and move to BaseRe
protected class RepresentNull implements RepresentToNode {
public Node representData(Object data) {
return representScalar(Tag.NULL, "null");
}
}
public static final Pattern MULTILINE_PATTERN = Pattern.compile("\n|\u0085|\u2028|\u2029");
protected class RepresentString implements RepresentToNode {
public Node representData(Object data) {
Tag tag = Tag.STR;
ScalarStyle style = ScalarStyle.PLAIN;
String value = data.toString();
if (settings.getNonPrintableStyle() == NonPrintableStyle.BINARY && !StreamReader.isPrintable(value)) {
tag = Tag.BINARY;
final byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
// sometimes above will just silently fail - it will return incomplete data
// it happens when String has invalid code points
// (for example half surrogate character without other half)
final String checkValue = new String(bytes, StandardCharsets.UTF_8);
if (!checkValue.equals(value)) {
throw new YamlEngineException("invalid string value has occurred");
}
value = Base64.getEncoder().encodeToString(bytes);
style = ScalarStyle.LITERAL;
}
// if no other scalar style is explicitly set, use literal style for
// multiline scalars
if (defaultScalarStyle == ScalarStyle.PLAIN && MULTILINE_PATTERN.matcher(value).find()) {
style = ScalarStyle.LITERAL;
}
return representScalar(tag, value, style);
}
}
protected class RepresentBoolean implements RepresentToNode {
public Node representData(Object data) {
String value;
if (Boolean.TRUE.equals(data)) {
value = "true";
} else {
value = "false";
}
return representScalar(Tag.BOOL, value);
}
}
protected class RepresentNumber implements RepresentToNode {
public Node representData(Object data) {
Tag tag;
String value;
if (data instanceof Byte || data instanceof Short || data instanceof Integer
|| data instanceof Long || data instanceof BigInteger) {
tag = Tag.INT;
value = data.toString();
} else {
Number number = (Number) data;
tag = Tag.FLOAT;
if (number.equals(Double.NaN)) {
value = ".NaN";
} else if (number.equals(Double.POSITIVE_INFINITY)) {
value = ".inf";
} else if (number.equals(Double.NEGATIVE_INFINITY)) {
value = "-.inf";
} else {
value = number.toString();
}
}
return representScalar(getTag(data.getClass(), tag), value);
}
}
protected class RepresentList implements RepresentToNode {
@SuppressWarnings("unchecked")
public Node representData(Object data) {
return representSequence(getTag(data.getClass(), Tag.SEQ), (List