diff --git a/src/main/java/org/fusionsoft/lib/text/IterableOfRegexpMatches.java b/src/main/java/org/fusionsoft/lib/text/IterableOfRegexpMatches.java new file mode 100644 index 0000000..4026220 --- /dev/null +++ b/src/main/java/org/fusionsoft/lib/text/IterableOfRegexpMatches.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018-2021 FusionSoft + * + * 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.fusionsoft.lib.text; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.cactoos.Func; +import org.cactoos.Scalar; +import org.cactoos.Text; +import org.cactoos.iterable.IterableEnvelope; +import org.cactoos.iterable.IterableOf; +import org.cactoos.text.TextOfString; + +public class IterableOfRegexpMatches extends IterableEnvelope { + + public IterableOfRegexpMatches( + final Scalar pattern, + final Func group, + final Text origin + ) { + super( + new IterableOf<>( + () -> { + final List matches = new ArrayList<>(); + final Matcher matcher = pattern.value().matcher(origin.asString()); + while (matcher.find()) { + matches.add(new TextOfString(group.apply(matcher))); + } + return matches.iterator(); + } + ) + ); + } + + public IterableOfRegexpMatches( + final Text regexp, + final Func group, + final Text origin + ) { + this( + () -> Pattern.compile(regexp.asString()), + group, + origin + ); + } + +} diff --git a/src/main/java/org/fusionsoft/lib/yaml/artefacts/RegexpOfFlowYamlSequenceValues.java b/src/main/java/org/fusionsoft/lib/yaml/artefacts/RegexpOfFlowYamlSequenceValues.java new file mode 100644 index 0000000..3b7f41d --- /dev/null +++ b/src/main/java/org/fusionsoft/lib/yaml/artefacts/RegexpOfFlowYamlSequenceValues.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018-2021 FusionSoft + * + * 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.fusionsoft.lib.yaml.artefacts; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.cactoos.scalar.Sticky; +import org.cactoos.scalar.Ternary; +import org.cactoos.scalar.Unchecked; + +public class RegexpOfFlowYamlSequenceValues { + + private final Unchecked scalar; + + public RegexpOfFlowYamlSequenceValues() { + this.scalar = new Unchecked<>( + new Sticky<>( + () -> Pattern.compile( + "(?:\\s*(?:\"((?>[^\"]|[\"]{2})*)\"|([^,]+))\\s*,?|(?<=,),?)+?" + ) + ) + ); + } + + public final Pattern pattern() { + return scalar.value(); + } + + public final String extract(final Matcher matcher) { + return new Unchecked<>( + new Ternary<>( + () -> matcher.group(1) == null, + () -> matcher.group(2), + () -> matcher.group(1) + ) + ).value(); + } + +} diff --git a/src/main/java/org/fusionsoft/lib/yaml/artefacts/TextIterableOfFlowYamlSequence.java b/src/main/java/org/fusionsoft/lib/yaml/artefacts/TextIterableOfFlowYamlSequence.java new file mode 100644 index 0000000..f049892 --- /dev/null +++ b/src/main/java/org/fusionsoft/lib/yaml/artefacts/TextIterableOfFlowYamlSequence.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018-2021 FusionSoft + * + * 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.fusionsoft.lib.yaml.artefacts; + +import com.amihaiemil.eoyaml.YamlNode; +import org.cactoos.Text; +import org.cactoos.iterable.IterableEnvelope; +import org.cactoos.iterable.Mapped; +import org.cactoos.text.Replaced; +import org.cactoos.text.Sub; +import org.fusionsoft.lib.text.IterableOfRegexpMatches; + +public class TextIterableOfFlowYamlSequence extends IterableEnvelope { + + public TextIterableOfFlowYamlSequence(final Text text, final RegexpOfFlowYamlSequenceValues regexp) { + super( + new Mapped( + x -> new Replaced(x, "\"\"", "\""), + new IterableOfRegexpMatches( + regexp::pattern, + regexp::extract, + new Sub( + text, + 1, + () -> text.asString().length() - 1 + ) + ) + ) + ); + } + + public TextIterableOfFlowYamlSequence(final Text text) { + this(text, new RegexpOfFlowYamlSequenceValues()); + } + + public TextIterableOfFlowYamlSequence(final YamlNode node) { + this(new TextOfScalarNode(node)); + } + +} diff --git a/src/test/java/org/fusionsoft/lib/yaml/artefacts/StringIterableOfTest.java b/src/test/java/org/fusionsoft/lib/yaml/artefacts/TextIterableOfFlowYamlSequenceTest.java similarity index 52% rename from src/test/java/org/fusionsoft/lib/yaml/artefacts/StringIterableOfTest.java rename to src/test/java/org/fusionsoft/lib/yaml/artefacts/TextIterableOfFlowYamlSequenceTest.java index 9f54d2d..627f9ed 100644 --- a/src/test/java/org/fusionsoft/lib/yaml/artefacts/StringIterableOfTest.java +++ b/src/test/java/org/fusionsoft/lib/yaml/artefacts/TextIterableOfFlowYamlSequenceTest.java @@ -17,22 +17,24 @@ import java.io.IOException; import org.cactoos.Text; +import org.cactoos.iterable.Mapped; import org.cactoos.map.MapEntry; -import org.cactoos.set.SetOf; import org.cactoos.text.TextOf; import org.fusionsoft.lib.yaml.YamlInputOf; import org.fusionsoft.lib.yaml.YamlMappingOf; import org.fusionsoft.lib.yaml.YamlMappingOfEntries; -import org.junit.jupiter.api.Assertions; +import org.fusionsoft.lib.yaml.YamlNodeOfPath; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.llorllale.cactoos.matchers.Assertion; +import org.llorllale.cactoos.matchers.HasValues; /** - * StringIterableOf tests. + * Tests for {@link TextIterableOfFlowYamlSequence} tests. * @since 0.1 */ @SuppressWarnings("PMD") -class StringIterableOfTest { +class TextIterableOfFlowYamlSequenceTest { @Test @Disabled @@ -50,41 +52,42 @@ public void canUseScalarOfText() throws IOException { } /** - * Can parse YAML array sequence of {@link com.amihaiemil.eoyaml.Scalar}. + * Can parse YAML flow sequence of {@link com.amihaiemil.eoyaml.Scalar}. */ @Test public void canParseArraySequence() { - Assertions.assertTrue( - new SetOf<>( - new StringSetOfYamlSequence( - new YamlMappingOf( - new YamlInputOf( - String.join( - "", - "data:\n", - " \"instanceStatus~ACTIVE\": ", - "[0, 1, \"ACTIVE\", \"ACTIVE\",null, null]\n", - " \"instanceStatus~DELETED\": ", - "[0, 2, \"DELETED\", \"DELETED\", null, null]" + new Assertion<>( + "Should have exact list of unescaped values", + new Mapped( + Text::asString, + new TextIterableOfFlowYamlSequence( + new YamlNodeOfPath( + new YamlMappingOf( + new YamlInputOf( + String.join( + "", + "data:\n", + " \"instanceStatus~ACTIVE\": ", + "[0, 1, \"ACTIVE\", \"ACTIVE\",null, null]\n", + " \"instanceStatus~DELETED\": ", + "[0, 2, \"D\\nELE\\TED,\", \"DEL\"\",\"\"ETED\", null, null]" + ) ) - ) + ), + "data", + "\"instanceStatus~DELETED\"" ) - .value("data") - .asMapping() - .value("\"instanceStatus~DELETED\"") - .asSequence() - ) - ).containsAll( - new SetOf<>( - "0", - "2", - "\"DELETED\"", - "\"DELETED\"", - "null", - "null" ) + ), + new HasValues<>( + "0", + "2", + "D\nELE\\TED,", + "DEL\",\"ETED", + "null", + "null" ) - ); + ).affirm(); } }