FileAndPathExtension.java

package org.freshmarker.file;

import org.freshmarker.api.FeatureSet;
import org.freshmarker.api.TemplateFeature;
import org.freshmarker.api.extension.BuiltInProvider;
import org.freshmarker.api.extension.Register;
import org.freshmarker.api.extension.TemplateFeatureProvider;
import org.freshmarker.api.extension.TemplateObjectProviders;
import org.freshmarker.api.extension.support.BuiltInRegister;
import org.freshmarker.core.ProcessContext;
import org.freshmarker.core.model.TemplateObject;
import org.freshmarker.core.providers.TemplateObjectProvider;

import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

public class FileAndPathExtension implements BuiltInProvider, TemplateObjectProviders, TemplateFeatureProvider {
    private boolean enabled;

    @Override
    public void init(FeatureSet featureSet) {
        enabled = featureSet.isEnabled(FileAndPathFeature.ENABLED);
    }

    private TemplateObject processFile(TemplateObject value, Function<File, ?> function, ProcessContext context) {
        File input = ((TemplateFile) value).getValue();
        return context.mapObject(function.apply(input));
    }

    private TemplateObject processFilePath(TemplateObject value, Function<File, ?> function, ProcessContext context) {
        Path input = ((TemplatePath) value).getValue();
        Function<Path, File> convert = Path::toFile;
        return context.mapObject(convert.andThen(function).apply(input));
    }

    private TemplateObject processPath(TemplateObject value, Function<Path, ?> function, ProcessContext context) {
        Path input = ((TemplatePath) value).getValue();
        return context.mapObject(function.apply(input));
    }

    @Override
    public Register<Class<? extends TemplateObject>, String, org.freshmarker.api.BuiltIn> provideBuiltInRegister() {
        BuiltInRegister register = new BuiltInRegister();
        if (!enabled) {
            return register;
        }
        register.add(TemplateFile.class, "exists", (x1, y1, e1) -> processFile(x1, File::exists, e1));
        register.add(TemplateFile.class, "is_directory", (x16, y16, e16) -> processFile(x16, File::isDirectory, e16));
        register.add(TemplateFile.class, "is_file", (x15, y15, e15) -> processFile(x15, File::isFile, e15));
        register.add(TemplateFile.class, "can_execute", (x14, y14, e14) -> processFile(x14, File::canExecute, e14));
        register.add(TemplateFile.class, "can_read", (x13, y13, e13) -> processFile(x13, File::canRead, e13));
        register.add(TemplateFile.class, "can_write", (x12, y12, e12) -> processFile(x12, File::canWrite, e12));
        register.add(TemplateFile.class, "size", (x11, y11, e11) -> processFile(x11, File::length, e11));
        register.add(TemplateFile.class, "name", (x10, y10, e10) -> processFile(x10, File::getName, e10));
        register.add(TemplateFile.class, "parent", (x9, y9, e9) -> processFile(x9, File::getParentFile, e9));
        register.add(TemplatePath.class, "exists", (x8, y8, e8) -> processFilePath(x8, File::exists, e8));
        register.add(TemplatePath.class, "is_directory", (x7, y7, e7) -> processFilePath(x7, File::isDirectory, e7));
        register.add(TemplatePath.class, "is_file", (x6, y6, e6) -> processFilePath(x6, File::isFile, e6));
        register.add(TemplatePath.class, "can_execute", (x5, y5, e5) -> processFilePath(x5, File::canExecute, e5));
        register.add(TemplatePath.class, "can_read", (x4, y4, e4) -> processFilePath(x4, File::canRead, e4));
        register.add(TemplatePath.class, "can_write", (x3, y3, e3) -> processFilePath(x3, File::canWrite, e3));
        register.add(TemplatePath.class, "size", (x2, y2, e2) -> processFilePath(x2, File::length, e2));
        register.add(TemplatePath.class, "name", (x1, y1, e1) -> processPath(x1, Path::getFileName, e1));
        register.add(TemplatePath.class, "parent", (x, y, e) -> processPath(x, Path::getParent, e));
        return register;
    }

    @Override
    public List<TemplateObjectProvider> provideProviders() {
        return !enabled ? List.of() : List.of(
                (environment, object) -> object instanceof Path path ? new TemplatePath(path) : null,
                (environment, object) -> object instanceof File file ? new TemplateFile(file) : null);
    }


    @Override
    public Set<TemplateFeature> provideFeatures() {
        return Set.of(FileAndPathFeature.ENABLED);
    }
}