diff --git a/metafix/src/main/java/org/metafacture/metafix/FindFixPaths.java b/metafix/src/main/java/org/metafacture/metafix/FindFixPaths.java new file mode 100644 index 00000000..5a9e6a24 --- /dev/null +++ b/metafix/src/main/java/org/metafacture/metafix/FindFixPaths.java @@ -0,0 +1,106 @@ +/* + * Copyright 2024 Tobias Bülte, hbz + * + * 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.metafacture.metafix; + +import org.metafacture.formatting.ObjectTemplate; +import org.metafacture.framework.FluxCommand; +import org.metafacture.framework.MetafactureException; +import org.metafacture.framework.ObjectReceiver; +import org.metafacture.framework.StreamReceiver; +import org.metafacture.framework.annotations.Description; +import org.metafacture.framework.annotations.In; +import org.metafacture.framework.annotations.Out; +import org.metafacture.framework.helpers.DefaultStreamPipe; +import org.metafacture.mangling.StreamFlattener; +import org.metafacture.triples.StreamToTriples; +import org.metafacture.triples.TripleFilter; + +import java.io.IOException; + +/** + * Provide a user-friendly way to finds all paths that have values that match + * the given pattern. + * + * @author Tobias Bülte + */ +@Description("Finds all paths that have values that match the given pattern. Allows for regex. These paths can be used in a Fix to address fields.") +@In(StreamReceiver.class) +@Out(String.class) +@FluxCommand("find-fix-paths") + +public class FindFixPaths extends DefaultStreamPipe> { + private final Metafix fix; + private String objectPattern; + + public FindFixPaths(final String objectPattern) { + this.objectPattern = objectPattern; + try { + this.fix = new Metafix("nothing()"); + this.fix.setRepeatedFieldsToEntities(true); + } + catch (final IOException e) { + throw new MetafactureException(e); + } + } + + @Override + protected void onSetReceiver() { + final TripleFilter tripleFilter = new TripleFilter(); + tripleFilter.setObjectPattern(objectPattern); + fix + .setReceiver(new StreamFlattener()) + .setReceiver(new StreamToTriples()) + .setReceiver(tripleFilter) + .setReceiver(new ObjectTemplate<>("${p}\\t|\\t${o}")) + .setReceiver(getReceiver()); + } + + @Override + public void startRecord(final String identifier) { + fix.startRecord(identifier); + } + + @Override + public void endRecord() { + fix.endRecord(); + } + + @Override + public void startEntity(final String name) { + fix.startEntity(name); + } + + @Override + public void endEntity() { + fix.endEntity(); + } + + @Override + public void literal(final String name, final String value) { + fix.literal(name, value); + } + + @Override + protected void onCloseStream() { + fix.closeStream(); + } + + @Override + protected void onResetStream() { + fix.resetStream(); + } +} diff --git a/metafix/src/main/resources/flux-commands.properties b/metafix/src/main/resources/flux-commands.properties index 808c4948..33cb50c2 100644 --- a/metafix/src/main/resources/flux-commands.properties +++ b/metafix/src/main/resources/flux-commands.properties @@ -15,3 +15,4 @@ fix org.metafacture.metafix.Metafix list-fix-paths org.metafacture.metafix.ListFixPaths list-fix-values org.metafacture.metafix.ListFixValues +find-fix-paths org.metafacture.metafix.FindFixPaths diff --git a/metafix/src/test/java/org/metafacture/metafix/FindFixPathsTest.java b/metafix/src/test/java/org/metafacture/metafix/FindFixPathsTest.java new file mode 100644 index 00000000..7ac8c5dd --- /dev/null +++ b/metafix/src/test/java/org/metafacture/metafix/FindFixPathsTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2024 Tobias Bülte, hbz + * + * 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.metafacture.metafix; + +import org.metafacture.framework.ObjectReceiver; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.exceptions.base.MockitoAssertionError; +import org.mockito.junit.jupiter.MockitoExtension; + +/** + * Tests for class {@link FindFixPaths}. + * + * @author Tobias Bülte + * + */ +@ExtendWith(MockitoExtension.class) +public final class FindFixPathsTest { + + private final FindFixPaths finder = new FindFixPaths(".*ETL.*"); + + @Mock + private ObjectReceiver receiver; + + public FindFixPathsTest() { + } + + @Test + public void testShouldFindPaths() { + verify( + "a\\t|\\tAn ETL test", + "c.2\\t|\\tETL what?"); + } + + private void processRecord() { + finder.setReceiver(receiver); + finder.startRecord(""); + finder.literal("a", "An ETL test"); + finder.literal("b", ""); + finder.literal("b", "Dummi"); + finder.literal("b", "Dog"); + finder.literal("c", ""); + finder.literal("c", "ETL what?"); + finder.endRecord(); + finder.closeStream(); + } + + private void verify(final String... result) throws MockitoAssertionError { + processRecord(); + try { + final InOrder ordered = Mockito.inOrder(receiver); + for (final String r : result) { + ordered.verify(receiver).process(r); + } + ordered.verify(receiver, Mockito.times(2)).closeStream(); + ordered.verifyNoMoreInteractions(); + Mockito.verifyNoMoreInteractions(receiver); + } + catch (final MockitoAssertionError e) { + System.out.println(Mockito.mockingDetails(receiver).printInvocations()); + throw e; + } + } + +}