package de.renew.formalism.fs;

import java.io.StringReader;
import java.util.Collection;

import de.renew.formalism.java.ArcFactory;
import de.renew.formalism.java.ArcInscription;
import de.renew.formalism.java.InscriptionParser;
import de.renew.formalism.java.ParsedDeclarationNode;
import de.renew.formalism.java.SingleJavaNetCompiler;
import de.renew.net.inscription.arc.Arc;
import de.renew.shadowcompiler.ShadowPreprocessor;
import de.renew.simulatorontology.shadow.ShadowNet;
import de.renew.simulatorontology.shadow.SyntaxException;


/**
 * Compiles Java nets with feature structure expressions and concept
 * preprocessing.  Instances of this class are created by the factory
 * {@link FSNetCompiler}.
 *
 * @author Frank Wienberg (FS-Net compiler)
 * @author Olaf Kummer (factory architecture)
 * @author Michael Duvigneau (documentation)
 * @since Renew 2.0
 **/
public class SingleFSNetCompiler extends SingleJavaNetCompiler {

    /**
     * Creates a new <code>SingleFSNetCompiler</code> instance.
     * <p>
     * The <code>SingleFSNetCompiler</code> is a specific
     * <code>SingleJavaNetCompiler</code> that allows dangerous arcs, but
     * no time inscriptions. It needs early tokens.
     * </p>
     **/
    public SingleFSNetCompiler() {
        super(true, false, true);
    }

    /**
     * The <code>SingleFSNetCompiler</code> needs a
     * {@link FSNetPreprocessor} to compile the concept system before the
     * nets are compiled.
     *
     * @return  {@inheritDoc}
     **/
    @Override
    public ShadowPreprocessor[] getRequiredPreprocessors() {
        return new ShadowPreprocessor[] { new FSNetPreprocessor() };
    }

    /**
     * The <code>SingleFSNetCompiler</code> provides the
     * {@link FSNetParser} to compile inscriptions.
     *
     * @param inscr  {@inheritDoc}
     * @return  {@inheritDoc}
     **/
    @Override
    protected InscriptionParser makeParser(String inscr) {
        return new de.renew.formalism.fs.FSNetParser(new StringReader(inscr));
    }

    /**
     * Parses the given arc inscription using the super class
     * implementation.  However, the empty inscription is parsed into an
     * empty feature structure.
     *
     * @param inscr {@inheritDoc}
     * @return {@inheritDoc}
     * @throws SyntaxException if the inscription cannot be parsed successfully.
     * @see SingleJavaNetCompiler#parseArcInscription(String)
     **/
    @Override
    protected Collection<ArcInscription> parseArcInscription(String inscr) throws SyntaxException {
        if (inscr == null || inscr.isEmpty()) {
            inscr = "[]";
        }
        return super.parseArcInscription(inscr);
    }

    /**
     * Creates an empty {@link ParsedFSDeclarationNode} for the given net.
     *
     * @param net {@inheritDoc}
     * @return {@inheritDoc}
     **/
    @Override
    protected ParsedDeclarationNode makeEmptyDeclarationNode(ShadowNet net) {
        if (net != null) {
            return new ParsedFSDeclarationNode(net.getName());
        }
        return new ParsedFSDeclarationNode();
    }

    /**
     * {@inheritDoc}
     *
     * @param arcType {@inheritDoc}
     * @param allowTime {@inheritDoc}
     * @return a <code>FSArcFactory</code> instance configured according to
     *   the method parameters.
     **/
    @Override
    protected ArcFactory getArcFactory(Arc.Type arcType, boolean allowTime) {
        return new FSArcFactory(arcType, allowTime);
    }
}