ChronoRepository.java

package org.docascode.api.core.chrono;

import org.apache.commons.io.FilenameUtils;
import org.docascode.api.core.chrono.generated.Maven;
import org.docascode.api.core.errors.DocAsCodeException;
import org.docascode.api.core.Substitute;
import org.docascode.api.core.chrono.generated.BaseArtifact;
import org.docascode.api.core.chrono.generated.Delivery;
import org.docascode.api.core.errors.ArtifactNotFoundException;
import org.docascode.api.core.errors.ProcessingException;
import org.docascode.api.core.office.Properties;
import org.docascode.api.event.Event;
import org.docascode.api.listener.EventListener;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.*;

public class ChronoRepository implements EventListener {
    private File chronoXML;

    private Delivery delivery = null;

    public ChronoRepository(File chronoXML){
        this.chronoXML = chronoXML;
    }

    private Delivery load() throws ProcessingException {
        try {
            JAXBContext context = JAXBContext.newInstance(Delivery.class);
            Unmarshaller un = context.createUnmarshaller();
            return (Delivery) un.unmarshal(chronoXML);
        } catch (JAXBException e) {
            throw new ProcessingException("Unable to unmarshal file "+chronoXML.getAbsolutePath(),e);
        }
    }

    public Delivery getDelivery() throws ProcessingException {
        if (delivery == null){
            delivery = load();
        }
        return delivery;
    }

    public void save(Delivery delivery) throws ProcessingException {
        this.delivery = delivery;
        try {
            JAXBContext context = JAXBContext.newInstance(Delivery.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(delivery, chronoXML);
        } catch (javax.xml.bind.JAXBException e) {
            throw new ProcessingException("Unable to marshal delivery to file "+chronoXML.getAbsolutePath(),e);
        }
    }

    public Map<String,Artifact> toArtifacts(List<String> ids) throws DocAsCodeException {
        Map<String,Artifact> result = new HashMap<>();
        List<Object> selectedIds;
        if (ids == null){
            selectedIds = Arrays.asList(getDelivery().getArtifacts().keySet().toArray());
        } else {
            selectedIds = Arrays.asList(ids.toArray());
        }
        for (Object id : selectedIds){
            org.docascode.api.core.chrono.generated.Artifact a = getDelivery().getArtifacts().get(id);
            if (a==null){
                throw new ArtifactNotFoundException(
                        String.format("Artifact '%s' not found.",
                                id));
            } else {
                Maven n = a.getMaven();
                if (n != null) {
                    if (a.getFile() == null) {
                        Event e = new Event(this);
                        e.setMessage(String.format(
                                "Main Artifact '%s' is not deployable since it has no 'file' field.", id)
                        );
                        fireEvent(e);
                    } else {
                        Map<String, String> dict = Properties.list(new File(a.getFile()));
                        org.eclipse.aether.artifact.Artifact artifact =
                                new DefaultArtifact(Substitute.substitute(n.getGroupId(), dict),
                                        Substitute.substitute(n.getArtifactId(), dict),
                                        Substitute.substitute("", dict),
                                        getExtension(a),
                                        Substitute.substitute(n.getVersion(), dict));
                        artifact = artifact.setFile(new File(a.getFile()));
                        result.put(a.getFile(),artifact);
                    }
                    if (a.getAttach() != null) {
                        for (Map.Entry<String, BaseArtifact> baseArtifactEntry : a.getAttach().entrySet()) {
                            BaseArtifact baseArtifact = baseArtifactEntry.getValue();
                            if (baseArtifact.getFile() == null) {
                                Event e = new Event(this);
                                e.setMessage(String.format(
                                        "Attached Artifact '%s:%s' is not deployable since it has no 'file' field.",
                                        id,
                                        baseArtifactEntry.getKey()));
                                fireEvent(e);
                            } else {
                                Map<String, String> dict = Properties.list(new File(baseArtifact.getFile()));
                                org.eclipse.aether.artifact.Artifact artifact =
                                        new DefaultArtifact(Substitute.substitute(n.getGroupId(), dict),
                                                Substitute.substitute(n.getArtifactId(), dict),
                                                Substitute.substitute(baseArtifactEntry.getKey(), dict),
                                                getExtension(baseArtifact),
                                                Substitute.substitute(n.getVersion(), dict));
                                artifact = artifact.setFile(new File(baseArtifact.getFile()));
                                result.put(baseArtifact.getFile(),artifact);
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

    private String getExtension(BaseArtifact artifact){
        if (artifact.getFile() != null){
            return FilenameUtils.getExtension(artifact.getFile());
        } else {
            return null;
        }
    }

    public Map<String,String> toMap(String name) throws ProcessingException {
        Map<String,String> result = new HashMap<>();
        for (org.docascode.api.core.chrono.generated.Artifact artifact : getDelivery().getArtifacts().values()){
            if (artifact.getFile() == null) {
                //Resolve artifact
            } else {
                result.put(artifact.getFile(),artifact.getOutputs().get(name));
            }
            if (artifact.getAttach() != null) {
                for (BaseArtifact baseArtifact : artifact.getAttach().values()) {
                    if (baseArtifact.getFile() == null) {
                        //Resolve artifact
                    } else {
                        result.put(baseArtifact.getFile(),
                                baseArtifact.getOutputs().get(name));
                    }
                }
            }
        }
        return result;
    }

    public ChronoRepository addListener(EventListener listener){
        this.listeners.add(listener);
        return this;
    }

    private Set<EventListener> listeners = new HashSet<>();

    @Override
    public void fireEvent(Event e){
        for (EventListener l : this.listeners){
            l.fireEvent(e);
        }
    }

    public List<String> toFileNames(List<String> ids) throws ArtifactNotFoundException, ProcessingException {
        List<String> result = new ArrayList<>();
        for (String id : ids){
            org.docascode.api.core.chrono.generated.Artifact a = getDelivery().getArtifacts().get(id);
            if (a==null){
                throw new ArtifactNotFoundException(
                        String.format("Artifact '%s' not found.",
                                id));
            } else {
                if (a.getFile() != null) {
                    result.add(a.getFile());
                    }
                if (a.getAttach() != null) {
                    for (Map.Entry<String, BaseArtifact> baseArtifactEntry : a.getAttach().entrySet()) {
                        BaseArtifact baseArtifact = baseArtifactEntry.getValue();
                        if (baseArtifact.getFile() != null) {
                            result.add(baseArtifact.getFile());
                        }
                    }
                }
            }
        }
        return result;
    }
}