/*
* Copyright 2013 Google Inc. All Rights Reserved.
*
* 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 com.google.jenkins.plugins.dsl.util;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.AbstractConstruct;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
import net.sf.json.JSONSerializer;
/**
* This class encapsulates the translation of a Yaml object into
* JSON, so Jenkins can data-bind it "as if" it were just submitted
* through its form configuration.
*
* NOTE: This is not round-trippable with {@link JsonToYaml} because
* the objects are stringified, flattening a possible DAG as a tree.
* see: $/dsl/src/test/resources/com/google/jenkins/plugins/dsl/util/hoist.yaml
* for an example of what the Yaml DSL allows, which the stringify
* would flatten.
*/
public abstract class YamlToJson {
/**
* This method is the workhorse method that implementations provide for
* translating yaml into json.
*/
public abstract String toJson(InputStream inputStream);
/** @see #toJson(InputStream) */
public final String toJson(String input) {
return toJson(new ByteArrayInputStream(input.getBytes(UTF_8)));
}
/** Stringify the object that results from loading the given Yaml */
public static class Default extends YamlToJson {
public Default() {
this(ImmutableList.<YamlTransform>of());
}
public Default(List<YamlTransform> transforms) {
this.transforms = checkNotNull(transforms);
}
/** {@inheritDoc} */
@Override
public String toJson(InputStream inputStream) {
// From Yaml to Object
Yaml yaml = new Yaml(new CustomConstructor(transforms));
// From Object to JSON (as string)
return JSONSerializer.toJSON(yaml.load(inputStream)).toString();
}
private final List<YamlTransform> transforms;
}
private static class CustomConstructor extends SafeConstructor {
public CustomConstructor(List<YamlTransform> transforms) {
for (YamlTransform xform : transforms) {
final String tag = xform.getTag();
this.yamlConstructors.put(new Tag(tag), new ConstructFoo(xform));
}
}
private class ConstructFoo extends AbstractConstruct {
public ConstructFoo(YamlTransform transform) {
this.transform = checkNotNull(transform);
}
public Object construct(Node node) {
final String val = (String) constructScalar((ScalarNode) node);
return transform.construct(val);
}
private final YamlTransform transform;
}
}
}