001/*
002 * JDrupes Builder
003 * Copyright (C) 2026 Michael N. Lipp
004 * 
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.builder.bnd;
020
021import aQute.bnd.osgi.Processor;
022import io.vavr.Tuple;
023import io.vavr.Tuple2;
024import java.io.IOException;
025import java.nio.file.Files;
026import java.nio.file.Path;
027import java.util.ArrayList;
028import java.util.List;
029import java.util.Map;
030import java.util.Properties;
031import org.jdrupes.builder.api.BuildException;
032import org.jdrupes.builder.api.Project;
033import org.jdrupes.builder.core.AbstractGenerator;
034
035// TODO: Auto-generated Javadoc
036/// A base class for providers using bndlib.
037///
038public abstract class AbstractBndGenerator extends AbstractGenerator {
039
040    private final List<Tuple2<String, String>> instructions = new ArrayList<>();
041
042    /// Initializes a new abstract bnd generator.
043    ///
044    /// @param project the project
045    ///
046    public AbstractBndGenerator(Project project) {
047        super(project);
048    }
049
050    /// Add the instruction specified by key and value.
051    ///
052    /// @param key the key
053    /// @param value the value
054    /// @return the bnd analyzer
055    ///
056    public AbstractBndGenerator instruction(String key, String value) {
057        instructions.add(Tuple.of(key, value));
058        return this;
059    }
060
061    /// Add the given instructions for the analyzer.
062    ///
063    /// @param instructions the instructions
064    /// @return the bnd analyzer
065    ///
066    public AbstractBndGenerator instructions(Map<String, String> instructions) {
067        instructions.forEach(this::instruction);
068        return this;
069    }
070
071    /// Add the instructions from the given bnd (properties) file.
072    ///
073    /// @param bndFile the bnd file
074    /// @return the bnd analyzer
075    ///
076    public AbstractBndGenerator instructions(Path bndFile) {
077        var props = new Properties();
078        try {
079            props.load(Files.newInputStream(bndFile));
080            props.forEach((k, v) -> instruction(k.toString(), v.toString()));
081        } catch (IOException e) {
082            throw new BuildException("Cannot read bnd file %s: %s", bndFile,
083                e).from(this).cause(e);
084        }
085        return this;
086    }
087
088    /// Apply the collected instructions to the given bnd processor.
089    ///
090    /// @param processor the processor
091    ///
092    protected void applyInstructions(Processor processor) {
093        instructions.forEach(t -> processor.setProperty(t._1, t._2));
094    }
095}