Skip to content

Commit

Permalink
Merge branch 'master' of ssh://git@github.com/culturegraph/metafactur…
Browse files Browse the repository at this point in the history
…e-core.git
  • Loading branch information
mgeipel committed Jun 10, 2013
2 parents 1ea56c4 + a62d463 commit 205a527
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 25 deletions.
86 changes: 65 additions & 21 deletions src/main/java/org/culturegraph/mf/Flux.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
Expand All @@ -34,13 +36,19 @@

/**
* @author Markus Michael Geipel
*
*
*/
public final class Flux {
public static final String MODULES_DIR = "modules";

private static final String JAR_FILE_EXTENSION = ".jar";
private static final String CLASS_FILE_EXTENSION = ".class";

private static final Pattern VAR_PATTERN = Pattern.compile("([^=]*)=(.*)");
private static final String SCRIPT_HOME = "FLUX_DIR";

private static final String MODULES_DIR_ARG = "-modules=";

private Flux() {
// no instances
}
Expand All @@ -49,34 +57,27 @@ private Flux() {
* @param args
* @throws IOException
* @throws RecognitionException
* @throws URISyntaxException
*/
public static void main(final String[] args) throws IOException, RecognitionException {

final File modulesDir = new File(MODULES_DIR);
if (modulesDir.exists()) {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.endsWith(".jar") || name.endsWith(".class");
}
};
final List<URL> moduleURLs = new LinkedList<URL>();
for (File file : modulesDir.listFiles(filter)) {
moduleURLs.add(file.getAbsoluteFile().toURI().toURL());
}
final URLClassLoader moduleLoader = new URLClassLoader(moduleURLs.toArray(new URL[0]), Thread
.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(moduleLoader);
loadModules(getModulesDir(args));

final int fileArg;
if (args.length > 0 && args[0].startsWith(MODULES_DIR_ARG)) {
fileArg = 1;
} else {
fileArg = 0;
}

if (args.length < 1) {
if (args.length < (fileArg + 1)) {
Flow.printHelp(System.out);
System.exit(2);
} else {

final File fluxFile = new File(args[0]);
final File fluxFile = new File(args[fileArg]);
if (!fluxFile.exists()) {
System.err.println("File not found: " + args[0]);
System.err.println("File not found: " + args[fileArg]);
System.exit(1);
return;
}
Expand All @@ -85,7 +86,10 @@ public boolean accept(final File dir, final String name) {
final Map<String, String> vars = new HashMap<String, String>();
vars.put(SCRIPT_HOME, fluxFile.getAbsoluteFile().getParent() + System.getProperty("file.separator"));

for (int i = 1; i < args.length; ++i) {
for (int i = fileArg + 1; i < args.length; ++i) {
if (args[i].startsWith(MODULES_DIR_ARG)) {
continue;
}
final Matcher matcher = VAR_PATTERN.matcher(args[i]);
if (!matcher.find()) {
Flow.printHelp(System.err);
Expand All @@ -96,11 +100,51 @@ public boolean accept(final File dir, final String name) {

// run parser and builder
final List<Flow> flows = FluxCompiler.compile(ResourceUtil.getStream(fluxFile), vars);
for (Flow flow : flows) {
for (final Flow flow : flows) {
flow.start();
}
}
}

private static File getModulesDir(final String[] args) {
File modulesDir = new File(MODULES_DIR);

File programDir = null;
try {
programDir = new File(Flux.class.getProtectionDomain().getCodeSource().getLocation().toURI());
} catch (final URISyntaxException e) {
// Ignore the programDir, if it is not available
}
if (programDir != null) {
if (programDir.getName().endsWith(JAR_FILE_EXTENSION)) {
programDir = programDir.getParentFile();
}
modulesDir = new File(programDir, MODULES_DIR);
}

if (args.length > 0 && args[0].startsWith(MODULES_DIR_ARG)) {
modulesDir = new File(args[0].substring(MODULES_DIR_ARG.length()));
}

return modulesDir;
}

private static void loadModules(final File modulesDir) throws MalformedURLException {
if (modulesDir.exists()) {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.endsWith(JAR_FILE_EXTENSION) || name.endsWith(CLASS_FILE_EXTENSION);
}
};
final List<URL> moduleURLs = new LinkedList<URL>();
for (final File file : modulesDir.listFiles(filter)) {
moduleURLs.add(file.getAbsoluteFile().toURI().toURL());
}
final URLClassLoader moduleLoader = new URLClassLoader(moduleURLs.toArray(new URL[0]), Thread
.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(moduleLoader);
}
}

}
71 changes: 71 additions & 0 deletions src/main/java/org/culturegraph/mf/morph/collectors/Range.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright 2013 Deutsche Nationalbibliothek
*
* 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.culturegraph.mf.morph.collectors;

import java.util.SortedSet;
import java.util.TreeSet;

import org.culturegraph.mf.morph.Metamorph;
import org.culturegraph.mf.morph.NamedValueSource;


/**
* Corresponds to the <code>&lt;range&gt;</code> tag.
*
* @author Christoph Böhme
*/
public final class Range extends AbstractCollect {
private final SortedSet<Integer> values = new TreeSet<Integer>();

private Integer first;

public Range(final Metamorph metamorph) {
super(metamorph);
setNamedValueReceiver(metamorph);
}

@Override
protected void emit() {
for (final Integer i: values) {
getNamedValueReceiver().receive(getName(), i.toString(), this, getRecordCount(), getEntityCount());
}
}

@Override
protected boolean isComplete() {
return false;
}

@Override
protected void receive(final String name, final String value, final NamedValueSource source) {
if (first == null) {
first = Integer.valueOf(value);
} else {
final int last = Integer.valueOf(value).intValue();
for (int i = first.intValue(); i <= last; ++i) {
values.add(Integer.valueOf(i));
}
first = null;
}
}

@Override
protected void clear() {
values.clear();
first = null;
}

}
3 changes: 2 additions & 1 deletion src/main/resources/morph-collectors.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ group org.culturegraph.mf.morph.collectors.Group
entity org.culturegraph.mf.morph.collectors.Entity
concat org.culturegraph.mf.morph.collectors.Concat
tuples org.culturegraph.mf.morph.collectors.Tuples
square org.culturegraph.mf.morph.collectors.Square
square org.culturegraph.mf.morph.collectors.Square
range org.culturegraph.mf.morph.collectors.Range
17 changes: 15 additions & 2 deletions src/main/resources/schemata/metamorph.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@
</element>

<element name="entity">
<annotation><documentation>Create an entity</documentation></annotation>
<annotation><documentation>Create an entity</documentation></annotation>
<complexType>
<choice minOccurs="1" maxOccurs="unbounded">
<element ref="tns:entity-name" minOccurs="0" maxOccurs="1" />
Expand All @@ -284,7 +284,19 @@
</complexType>
</element>


<element name="range">
<annotation><documentation>Interprets pairs of consecutive literals as integer range start and end. For each number between the two an additional literal is generated.</documentation></annotation>
<complexType>
<sequence>
<group ref="tns:literal-rule" minOccurs="1" maxOccurs="unbounded" />
<element ref="tns:postprocess" minOccurs="0" maxOccurs="1" />
</sequence>
<attribute name="name" type="string" use="required" />
<attribute name="reset" type="boolean" use="optional" default="false" />
<attribute name="sameEntity" type="boolean" use="optional" default="false" />
<attribute name="flushWith" type="string" use="optional" default="record"/>
</complexType>
</element>

<element name="data">
<annotation><documentation>Used to receive literals</documentation></annotation>
Expand Down Expand Up @@ -441,6 +453,7 @@
<element ref="tns:concat" />
<element ref="tns:square" />
<element ref="tns:tuples" />
<element ref="tns:range" />
</choice>
</group>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
*/
@RunWith(TestSuite.class)
@TestDefinitions({ "CombineTest.xml", "GroupTest.xml", "ChooseTest.xml", "EntityTest.xml", "ConcatTest.xml",
"Nested.xml", "NestedEntity.xml", "TuplesTest.xml", "Misc.xml", "SquareTest.xml" })
"Nested.xml", "NestedEntity.xml", "TuplesTest.xml", "Misc.xml", "SquareTest.xml", "RangeTest.xml" })
public final class CollectorTest {/* bind to xml test */
}
Loading

0 comments on commit 205a527

Please sign in to comment.