package com.tinkerpop.rexster.config;

import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.IndexableGraph;
import com.tinkerpop.blueprints.util.wrappers.readonly.ReadOnlyGraph;
import com.tinkerpop.blueprints.util.wrappers.readonly.ReadOnlyIndexableGraph;
import com.tinkerpop.rexster.RexsterApplicationGraph;
import com.tinkerpop.rexster.Tokens;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
public class GraphConfigurationContainer {

    protected static final Logger logger = Logger.getLogger(GraphConfigurationContainer.class);

    private final Map<String, RexsterApplicationGraph> graphs = new HashMap<String, RexsterApplicationGraph>();

    private final List<HierarchicalConfiguration> failedConfigurations = new ArrayList<HierarchicalConfiguration>();

    public GraphConfigurationContainer(final List<HierarchicalConfiguration> configurations) throws GraphConfigurationException {

        if (configurations == null) {
            throw new GraphConfigurationException("No graph configurations");
        }

        // create one graph for each configuration for each <graph> element
        final Iterator<HierarchicalConfiguration> it = configurations.iterator();
        while (it.hasNext()) {
            final HierarchicalConfiguration graphConfig = it.next();
            final String graphName = graphConfig.getString(Tokens.REXSTER_GRAPH_NAME, "");

            if (graphName.equals("")) {
                // all graphs must have a graph name
                logger.warn("Could not load graph " + graphName + ".  The graph-name element was not set.");
                this.failedConfigurations.add(graphConfig);
            } else {
                // check for duplicate graph configuration
                if (!this.graphs.containsKey(graphName)) {

                    if (graphConfig.getBoolean(Tokens.REXSTER_GRAPH_ENABLED, true)) {

                        // one graph failing initialization will not prevent the rest in
                        // their attempt to be created
                        try {
                            final Graph graph = getGraphFromConfiguration(graphConfig);
                            final RexsterApplicationGraph rag = new RexsterApplicationGraph(graphName, graph, graphConfig);
                            this.graphs.put(rag.getGraphName(), rag);

                            logger.info("Graph " + graphName + " - " + graph + " loaded");
                        } catch (GraphConfigurationException gce) {
                            logger.warn("Could not load graph " + graphName + ". Please check the XML configuration.");
                            logger.warn(gce.getMessage(), gce);

                            if (gce.getCause() != null) {
                                logger.warn(gce.getCause().getMessage(), gce.getCause());
                            }

                            failedConfigurations.add(graphConfig);
                        } catch (Exception e) {
                            logger.warn("Could not load graph " + graphName + ".", e);

                            failedConfigurations.add(graphConfig);
                        }
                    } else {
                        logger.info("Graph " + graphName + " - " + " not enabled and not loaded.");
                    }
                } else {
                    logger.warn("A graph with the name " + graphName + " was already configured.  Please check the XML configuration.");

                    failedConfigurations.add(graphConfig);
                }
            }
        }
    }

    public Map<String, RexsterApplicationGraph> getApplicationGraphs() {
        return this.graphs;
    }

    public List<HierarchicalConfiguration> getFailedConfigurations() {
        return this.failedConfigurations;
    }

    private Graph getGraphFromConfiguration(final HierarchicalConfiguration graphConfiguration) throws GraphConfigurationException {
        String graphConfigurationType = graphConfiguration.getString(Tokens.REXSTER_GRAPH_TYPE);
        final boolean isReadOnly = graphConfiguration.getBoolean(Tokens.REXSTER_GRAPH_READ_ONLY, false);

        if (graphConfigurationType.equals("idgraph")) {
            graphConfigurationType = IdGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("neo4jgraph")) {
            graphConfigurationType = Neo4jGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("orientgraph")) {
            graphConfigurationType = "com.tinkerpop.blueprints.impls.orient.OrientGraphRexsterConfiguration";
        } else if (graphConfigurationType.equals("tinkergraph")) {
            graphConfigurationType = TinkerGraphGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("rexstergraph")) {
            graphConfigurationType = RexsterGraphGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("linkeddatasailgraph")) {
            graphConfigurationType = LinkedDataSailGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("memorystoresailgraph")) {
            graphConfigurationType = MemoryStoreSailGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("nativestoresailgraph")) {
            graphConfigurationType = NativeStoreSailGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("sparqlrepositorysailgraph")) {
            graphConfigurationType = SparqlRepositorySailGraphConfiguration.class.getName();
        } else if (graphConfigurationType.equals("sparkseegraph")) {
            graphConfigurationType = SparkseeGraphConfiguration.class.getName();
        }

        final Graph graph;
        try {
            final Class clazz = Class.forName(graphConfigurationType, true, Thread.currentThread().getContextClassLoader());
            final GraphConfiguration graphConfigInstance = (GraphConfiguration) clazz.newInstance();

            GraphConfigurationContext context = new GraphConfigurationContext(graphConfiguration, getApplicationGraphs());

            Graph readWriteGraph = graphConfigInstance.configureGraphInstance(context);

            if (isReadOnly) {
                // the graph is configured to be readonly so wrap it up
                if (readWriteGraph instanceof IndexableGraph) {
                    graph = new ReadOnlyIndexableGraph((IndexableGraph) readWriteGraph);
                } else {
                    graph = new ReadOnlyGraph(readWriteGraph);
                }
            } else {
                graph = readWriteGraph;
            }

        } catch (NoClassDefFoundError err) {
            throw new GraphConfigurationException(String.format(
                    "GraphConfiguration [%s] could not instantiate a class [%s].  Ensure that it is in Rexster's path.",
                    graphConfigurationType, err.getMessage()));
        } catch (Exception ex) {
            throw new GraphConfigurationException(String.format(
                    "GraphConfiguration could not be found or otherwise instantiated: [%s]. Ensure that it is in Rexster's path.",
                    graphConfigurationType), ex);
        }

        return graph;
    }
}

@@ -4673,184 +4673,8 @@
   %7D 
-else if (graphConfigurationType.equals(%22orientgraph%22)) %7B%0A            graphConfigurationType = %22com.tinkerpop.blueprints.impls.orient.OrientGraphRexsterConfiguration%22;%0A        %7D
  els

Remove orientdb shorthand configuration.