
javax0.jamal.builtins.Import Maven / Gradle / Ivy
package javax0.jamal.builtins;
import javax0.jamal.api.BadSyntax;
import javax0.jamal.api.Input;
import javax0.jamal.api.Processor;
import javax0.jamal.api.Stackable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static javax0.jamal.tools.FileTools.absolute;
import static javax0.jamal.tools.FileTools.getInput;
import static javax0.jamal.tools.InputHandler.skipWhiteSpaces;
/**
* Imports the macros from the file.
*
* The file name is followed by the macro keyword {@code import}. If the file was already
* imported on the actual level or some higher level then the file will not be imported
* again. This is to ensure that the same macro file will not be imported uselessly more
* than once. Also if the macro file was imported on a level that is deeper than the current
* level then the macros are not available at the current position (except those that were
* exported) and therefore in that case the file will be imported again.
*
* The output generated from the file is ignored and is thrown away.
*/
public class Import implements Stackable {
private final List> importedAlready = new ArrayList<>();
{
push();
}
@Override
public String evaluate(Input input, Processor processor) throws BadSyntax {
skipWhiteSpaces(input);
String reference = input.getReference();
String fileName = absolute(reference, input.toString().trim());
if (wasNotImported(fileName)) {
importedAlready.get(importedAlready.size() - 1).add(fileName);
processor.process(getInput(fileName));
}
return "";
}
private boolean wasNotImported(String fileName) {
for (int level = importedAlready.size() - 1; level > -1; level--) {
Set importSet = importedAlready.get(level);
if (importSet.contains(fileName)) {
return false;
}
}
return true;
}
@Override
public void push() {
importedAlready.add(new HashSet<>());
}
@Override
public void pop() {
importedAlready.remove(importedAlready.size() - 1);
}
}