All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.yaml.YamlParser Maven / Gradle / Ivy

/*
 * Copyright 2020 the original author or authors.
 * 

* 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 *

* https://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.openrewrite.yaml; import org.openrewrite.Formatting; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.yaml.tree.Yaml; import org.yaml.snakeyaml.events.Event; import org.yaml.snakeyaml.events.ScalarEvent; import org.yaml.snakeyaml.parser.Parser; import org.yaml.snakeyaml.parser.ParserImpl; import org.yaml.snakeyaml.reader.StreamReader; import org.yaml.snakeyaml.scanner.Scanner; import org.yaml.snakeyaml.scanner.ScannerImpl; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UncheckedIOException; import java.net.URI; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.stream.Stream; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toList; import static org.openrewrite.Formatting.format; import static org.openrewrite.Tree.randomId; public class YamlParser implements org.openrewrite.Parser { @Override public List parseInputs(Iterable sourceFiles, @Nullable Path relativeTo) { return acceptedInputs(sourceFiles).stream() .map(sourceFile -> { try (InputStream is = sourceFile.getSource()) { return parseFromInput(sourceFile.getRelativePath(relativeTo), is); } catch (IOException e) { throw new UncheckedIOException(e); } }).collect(toList()); } private Yaml.Documents parseFromInput(Path sourceFile, InputStream source) { try (FormatPreservingReader reader = new FormatPreservingReader(new InputStreamReader(source))) { StreamReader streamReader = new StreamReader(reader); Scanner scanner = new ScannerImpl(streamReader); Parser parser = new ParserImpl(scanner); int lastEnd = 0; List documents = new ArrayList<>(); Yaml.Document document = null; Stack blockStack = new Stack<>(); for (Event event = parser.getEvent(); event != null; event = parser.getEvent()) { Formatting fmt = reader.prefix(lastEnd, event); switch (event.getEventId()) { case Alias: break; case DocumentEnd: documents.add(document); break; case DocumentStart: document = new Yaml.Document( randomId(), event.getEndMark().getIndex() - event.getStartMark().getIndex() > 0, emptyList(), null, fmt ); lastEnd = event.getEndMark().getIndex(); break; case MappingStart: blockStack.push(new MappingBuilder(fmt)); break; case Scalar: ScalarEvent scalar = (ScalarEvent) event; Yaml.Scalar.Style style; switch (scalar.getScalarStyle()) { case DOUBLE_QUOTED: style = Yaml.Scalar.Style.DOUBLE_QUOTED; break; case SINGLE_QUOTED: style = Yaml.Scalar.Style.SINGLE_QUOTED; break; case LITERAL: style = Yaml.Scalar.Style.LITERAL; break; case FOLDED: style = Yaml.Scalar.Style.FOLDED; break; case PLAIN: default: style = Yaml.Scalar.Style.PLAIN; break; } blockStack.peek().push(new Yaml.Scalar(randomId(), style, scalar.getValue(), fmt)); lastEnd = event.getEndMark().getIndex(); break; case SequenceEnd: case MappingEnd: Yaml.Block mappingOrSequence = blockStack.pop().build(); if (blockStack.isEmpty()) { //noinspection ConstantConditions document = document.withBlocks(Stream.concat( document.getBlocks().stream(), Stream.of(mappingOrSequence) ).collect(toList())); } else { blockStack.peek().push(mappingOrSequence); } break; case SequenceStart: blockStack.push(new SequenceBuilder(fmt)); break; case StreamEnd: case StreamStart: break; } } return new Yaml.Documents(randomId(), sourceFile, emptyList(), documents, Formatting.EMPTY); } catch (IOException e) { throw new UncheckedIOException(e); } } @Override public boolean accept(Path path) { String fileName = path.toString(); return fileName.endsWith(".yml") || fileName.endsWith(".yaml"); } private interface BlockBuilder { Yaml.Block build(); void push(Yaml.Block block); } private static class MappingBuilder implements BlockBuilder { private final Formatting formatting; private final List entries = new ArrayList<>(); @Nullable private Yaml.Scalar key; private MappingBuilder(Formatting formatting) { this.formatting = formatting; } public void push(Yaml.Block block) { if (key == null && block instanceof Yaml.Scalar) { key = (Yaml.Scalar) block; } else { String keySuffix = block.getPrefix(); block = block.withPrefix(keySuffix.substring(keySuffix.lastIndexOf(':') + 1)); String keyPrefix = key.getPrefix(); key = key.withFormatting(format( "", keySuffix.substring(0, keySuffix.lastIndexOf(':')) )); entries.add(new Yaml.Mapping.Entry(randomId(), key, block, format(keyPrefix.substring(keyPrefix.lastIndexOf(':') + 1)))); key = null; } } public Yaml.Mapping build() { return new Yaml.Mapping(randomId(), entries, formatting); } } private static class SequenceBuilder implements BlockBuilder { private final Formatting formatting; private final List entries = new ArrayList<>(); private SequenceBuilder(Formatting formatting) { this.formatting = formatting; } @Override public void push(Yaml.Block block) { String entryPrefix = block.getPrefix(); block = block.withPrefix(entryPrefix.substring(entryPrefix.lastIndexOf('-') + 1)); entryPrefix = entryPrefix.substring(0, entryPrefix.lastIndexOf('-')); entries.add(new Yaml.Sequence.Entry(randomId(), block, format(entryPrefix))); } public Yaml.Sequence build() { return new Yaml.Sequence(randomId(), entries, formatting); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy