/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.rya.api;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.hadoop.conf.Configuration;
import org.apache.rya.api.domain.RyaURI;
import org.apache.rya.api.layout.TableLayoutStrategy;
import org.apache.rya.api.layout.TablePrefixLayoutStrategy;
import org.apache.rya.api.persist.RdfEvalStatsDAO;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

/**
 * Rdf triple store specific configuration
 */
public abstract class RdfCloudTripleStoreConfiguration extends Configuration {

    //    public static final String CONF_ISQUERYTIMEBASED = "query.timebased";
    public static final String CONF_TTL = "query.ttl";
    public static final String CONF_STARTTIME = "query.startTime";
    //    public static final String CONF_TIMEINDEXURIS = "query.timeindexuris";
    public static final String CONF_NUM_THREADS = "query.numthreads";
    public static final String CONF_PERFORMANT = "query.performant";
    public static final String CONF_INFER = "query.infer";
    public static final String CONF_USE_STATS = "query.usestats";
    public static final String CONF_USE_COMPOSITE = "query.usecompositecard";
    public static final String CONF_USE_SELECTIVITY = "query.useselectivity";
    public static final String CONF_TBL_PREFIX = "query.tblprefix";
    public static final String CONF_BATCH_SIZE = "query.batchsize";
    public static final String CONF_OFFSET = "query.offset";
    public static final String CONF_LIMIT = "query.limit";
    public static final String CONF_QUERYPLAN_FLAG = "query.printqueryplan";
    public static final String CONF_QUERY_AUTH = "query.auth";
    public static final String CONF_RESULT_FORMAT = "query.resultformat";
    public static final String CONF_CV = "conf.cv";
    public static final String CONF_TBL_SPO = "tbl.spo";
    public static final String CONF_TBL_PO = "tbl.po";
    public static final String CONF_TBL_OSP = "tbl.osp";
    public static final String CONF_TBL_NS = "tbl.ns";
    public static final String CONF_TBL_EVAL = "tbl.eval";
    public static final String CONF_PREFIX_ROW_WITH_HASH = "tbl.hashprefix";
    public static final String CONF_OPTIMIZERS = "query.optimizers";
    public static final String CONF_PCJ_OPTIMIZER = "pcj.query.optimizer";
    public static final String CONF_PCJ_TABLES = "pcj.index.tables";
    public static final String CONF_STATEMENT_METADATA_PROPERTIES = "statement.metadata.properites";
    public static final String CONF_USE_STATEMENT_METADATA = "use.statement.metadata";
    public static final String STATS_PUSH_EMPTY_RDFTYPE_DOWN = "conf.stats.rdftype.down";
    public static final String INFER_INCLUDE_ALL_VALUES_FROM = "infer.include.allvaluesfrom";
    public static final String INFER_INCLUDE_DOMAIN_RANGE = "infer.include.domainrange";
    public static final String INFER_INCLUDE_HAS_SELF = "infer.include.hasself";
    public static final String INFER_INCLUDE_HAS_VALUE = "infer.include.hasvalue";
    public static final String INFER_INCLUDE_INTERSECTION_OF = "infer.include.intersectionof";
    public static final String INFER_INCLUDE_INVERSEOF = "infer.include.inverseof";
    public static final String INFER_INCLUDE_ONE_OF = "infer.include.oneof";
    public static final String INFER_INCLUDE_PROPERTY_CHAIN = "infer.include.propertychain";
    public static final String INFER_INCLUDE_REFLEXIVE_PROP = "infer.include.reflexiveprop";
    public static final String INFER_INCLUDE_SOME_VALUES_FROM = "infer.include.somevaluesfrom";
    public static final String INFER_INCLUDE_SAME_AS = "infer.include.sameas";
    public static final String INFER_INCLUDE_SUBCLASSOF = "infer.include.subclassof";
    public static final String INFER_INCLUDE_SUBPROPOF = "infer.include.subpropof";
    public static final String INFER_INCLUDE_SYMMPROP = "infer.include.symmprop";
    public static final String INFER_INCLUDE_TRANSITIVEPROP = "infer.include.transprop";

    public static final String RDF_DAO_CLASS = "class.rdf.dao";
    public static final String RDF_EVAL_STATS_DAO_CLASS = "class.rdf.evalstats";

    public static final String REGEX_SUBJECT = "query.regex.subject";
    public static final String REGEX_PREDICATE = "query.regex.predicate";
    public static final String REGEX_OBJECT = "query.regex.object";
    private static final String[] EMPTY_STR_ARR = new String[0];

    private TableLayoutStrategy tableLayoutStrategy = new TablePrefixLayoutStrategy();

    public RdfCloudTripleStoreConfiguration() {
    }

    public RdfCloudTripleStoreConfiguration(final Configuration other) {
        super(other);
        if (other instanceof RdfCloudTripleStoreConfiguration) {
            setTableLayoutStrategy(((RdfCloudTripleStoreConfiguration) other).getTableLayoutStrategy());
        }
    }

    @Override
    public abstract RdfCloudTripleStoreConfiguration clone();

    public TableLayoutStrategy getTableLayoutStrategy() {
        return tableLayoutStrategy;
    }

    public void setTableLayoutStrategy(final TableLayoutStrategy tableLayoutStrategy) {
        if (tableLayoutStrategy != null) {
            this.tableLayoutStrategy = tableLayoutStrategy;
        } else {
            this.tableLayoutStrategy = new TablePrefixLayoutStrategy(); //default
        }
        set(CONF_TBL_SPO, this.tableLayoutStrategy.getSpo());
        set(CONF_TBL_PO, this.tableLayoutStrategy.getPo());
        set(CONF_TBL_OSP, this.tableLayoutStrategy.getOsp());
        set(CONF_TBL_NS, this.tableLayoutStrategy.getNs());
        set(CONF_TBL_EVAL, this.tableLayoutStrategy.getEval());
    }

    public Long getTtl() {
        final String val = get(CONF_TTL);
        if (val != null) {
            return Long.valueOf(val);
        }
        return null;
    }

    public void setTtl(final Long ttl) {
        Preconditions.checkNotNull(ttl);
        Preconditions.checkArgument(ttl >= 0, "ttl must be non negative");
        set(CONF_TTL, ttl.toString());
    }

    public Long getStartTime() {
        final String val = get(CONF_STARTTIME);
        if (val != null) {
            return Long.valueOf(val);
        }
        return null;
    }

    public void setStartTime(final Long startTime) {
        Preconditions.checkNotNull(startTime);
        Preconditions.checkArgument(startTime >= 0, "startTime must be non negative");
        set(CONF_STARTTIME, startTime.toString());
    }

    public Integer getNumThreads() {
        return getInt(CONF_NUM_THREADS, 2);
    }

    public void setNumThreads(final Integer numThreads) {
        Preconditions.checkNotNull(numThreads);
        Preconditions.checkArgument(numThreads > 0, "numThreads must be greater than 0");
        setInt(CONF_NUM_THREADS, numThreads);
    }

    public Boolean isPerformant() {
        return getBoolean(CONF_PERFORMANT, true);
    }

    public void setPerformant(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_PERFORMANT, val);
    }

    public Boolean isInfer() {
        return getBoolean(CONF_INFER, false);
    }

    public void setInfer(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_INFER, val);
    }

    public Boolean isUseStats() {
        return getBoolean(CONF_USE_STATS, false);
    }

    public void setUseStats(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_USE_STATS, val);
    }

    public Boolean isUseSelectivity() {
        return getBoolean(CONF_USE_SELECTIVITY, false);
    }

    public void setUseSelectivity(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_USE_SELECTIVITY, val);
    }

    public Boolean isPrefixRowsWithHash() {
        return getBoolean(CONF_PREFIX_ROW_WITH_HASH, false);
    }

    public void setPrefixRowsWithHash(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_PREFIX_ROW_WITH_HASH, val);
    }

    public String getTablePrefix() {
        return get(CONF_TBL_PREFIX, RdfCloudTripleStoreConstants.TBL_PRFX_DEF);
    }

    public void setTablePrefix(final String tablePrefix) {
        Preconditions.checkNotNull(tablePrefix);
        set(CONF_TBL_PREFIX, tablePrefix);
        setTableLayoutStrategy(new TablePrefixLayoutStrategy(tablePrefix)); //TODO: Should we change the layout strategy
    }

    public Integer getBatchSize() {
        final String val = get(CONF_BATCH_SIZE);
        if (val != null) {
            return Integer.valueOf(val);
        }
        return null;
    }

    public void setBatchSize(final Long batchSize) {
        Preconditions.checkNotNull(batchSize);
        Preconditions.checkArgument(batchSize > 0, "Batch Size must be greater than 0");
        setLong(CONF_BATCH_SIZE, batchSize);
    }

    public Long getOffset() {
        final String val = get(CONF_OFFSET);
        if (val != null) {
            return Long.valueOf(val);
        }
        return null;
    }

    public void setOffset(final Long offset) {
        Preconditions.checkNotNull(offset);
        Preconditions.checkArgument(offset >= 0, "offset must be positive");
        setLong(CONF_OFFSET, offset);
    }

    public Long getLimit() {
        final String val = get(CONF_LIMIT);
        if (val != null) {
            return Long.valueOf(val);
        }
        return null;
    }

    public void setLimit(final Long limit) {
        Preconditions.checkNotNull(limit);
        Preconditions.checkArgument(limit >= 0, "limit must be positive");
        setLong(CONF_LIMIT, limit);
    }


    public Boolean isDisplayQueryPlan() {
        return getBoolean(CONF_QUERYPLAN_FLAG, false);
    }

    public void setDisplayQueryPlan(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_QUERYPLAN_FLAG, val);
    }

    /**
     * @return
     * @deprecated
     */
    @Deprecated
    public String getAuth() {
        return Joiner.on(",").join(getAuths());
    }

    /**
     * @param auth
     * @deprecated
     */
    @Deprecated
    public void setAuth(final String auth) {
        Preconditions.checkNotNull(auth);
        setStrings(CONF_QUERY_AUTH, auth);
    }

    public String[] getAuths() {
        return getStrings(CONF_QUERY_AUTH, EMPTY_STR_ARR);
    }

    public void setAuths(final String... auths) {
        Preconditions.checkNotNull(auths);
        setStrings(CONF_QUERY_AUTH, auths);
    }

    public String getEmit() {
        return get(CONF_RESULT_FORMAT);
    }

    public void setEmit(final String emit) {
        Preconditions.checkNotNull(emit);
        set(CONF_RESULT_FORMAT, emit);
    }

    public String getCv() {
        return get(CONF_CV);
    }

    public void setCv(final String cv) {
        Preconditions.checkNotNull(cv);
        set(CONF_CV, cv);
    }


    public Boolean isUseCompositeCardinality() {
        return getBoolean(CONF_USE_COMPOSITE, true);
    }

    public void setCompositeCardinality(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(CONF_USE_COMPOSITE, val);
    }


    public Boolean isStatsPushEmptyRdftypeDown() {
        return getBoolean(STATS_PUSH_EMPTY_RDFTYPE_DOWN, true);
    }

    public void setStatsPushEmptyRdftypeDown(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(STATS_PUSH_EMPTY_RDFTYPE_DOWN, val);
    }

    /**
     * @return {@code true} if owl:allValuesFrom inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferAllValuesFrom() {
        return getBoolean(INFER_INCLUDE_ALL_VALUES_FROM, true);
    }

    /**
     * Sets whether owl:allValuesFrom inferencing is enabled or disabled.
     * @param value {@code true} if owl:allValuesFrom inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferAllValuesFrom(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_ALL_VALUES_FROM, value);
    }

    /**
     * @return {@code true} if rdfs:domain and rdfs:range inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferDomainRange() {
        return getBoolean(INFER_INCLUDE_DOMAIN_RANGE, true);
    }

    /**
     * Sets whether rdfs:domain and rdfs:range inferencing is enabled or disabled.
     * @param val {@code true} if rdfs:domain/range inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferDomainRange(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_DOMAIN_RANGE, val);
    }

    /**
     * @return {@code true} if owl:hasSelf inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferHasSelf() {
        return getBoolean(INFER_INCLUDE_HAS_SELF, true);
    }

    /**
     * Sets whether owl:hasSelf inferencing is enabled or disabled.
     * @param val {@code true} if owl:hasSelf inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferHasSelf(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_HAS_SELF, val);
    }

    /**
     * @return {@code true} if owl:hasValue inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferHasValue() {
        return getBoolean(INFER_INCLUDE_HAS_VALUE, true);
    }

    /**
     * Sets whether owl:hasValue inferencing is enabled or disabled.
     * @param value {@code true} if owl:hasValue inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferHasValue(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_HAS_VALUE, value);
    }

    /**
     * @return {@code true} if owl:intersectionOf inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferIntersectionOf() {
        return getBoolean(INFER_INCLUDE_INTERSECTION_OF, true);
    }

    /**
     * Sets whether owl:intersectionOf inferencing is enabled or disabled.
     * @param value {@code true} if owl:intersectionOf inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferIntersectionOf(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_INTERSECTION_OF, value);
    }

    /**
     * @return {@code true} if owl:inverseOf inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferInverseOf() {
        return getBoolean(INFER_INCLUDE_INVERSEOF, true);
    }

    /**
     * Sets whether owl:inverseOf inferencing is enabled or disabled.
     * @param val {@code true} if owl:inverseOf inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferInverseOf(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_INVERSEOF, val);
    }

    /**
     * @return {@code true} if owl:oneOf inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferOneOf() {
        return getBoolean(INFER_INCLUDE_ONE_OF, true);
    }

    /**
     * Sets whether owl:oneOf inferencing is enabled or disabled.
     * @param value {@code true} if owl:oneOf inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferOneOf(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_ONE_OF, value);
    }

    /**
     * @return {@code true} if owl:propertyChainAxiom inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferPropertyChain() {
        return getBoolean(INFER_INCLUDE_PROPERTY_CHAIN, true);
    }

    /**
     * Sets whether owl:propertyChainAxiom inferencing is enabled or disabled.
     * @param value {@code true} if owl:propertyChainAxiom inferencing is
     * enabled. {@code false} otherwise.
     */
    public void setInferPropertyChain(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_PROPERTY_CHAIN, value);
    }

    /**
     * @return {@code true} if owl:ReflexiveProperty inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferReflexiveProperty() {
        return getBoolean(INFER_INCLUDE_REFLEXIVE_PROP, true);
    }

    /**
     * Sets whether owl:ReflexiveProperty inferencing is enabled or disabled.
     * @param value {@code true} if owl:ReflexiveProperty inferencing is
     * enabled. {@code false} otherwise.
     */
    public void setInferReflexiveProperty(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_REFLEXIVE_PROP, value);
    }

    /**
     * @return {@code true} if owl:sameAs inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferSameAs() {
        return getBoolean(INFER_INCLUDE_SAME_AS, true);
    }

    /**
     * Sets whether owl:sameAs inferencing is enabled or disabled.
     * @param value {@code true} if owl:sameAs inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferSameAs(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_SAME_AS, value);
    }

    /**
     * @return {@code true} if owl:someValuesFrom inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferSomeValuesFrom() {
        return getBoolean(INFER_INCLUDE_SOME_VALUES_FROM, true);
    }

    /**
     * Sets whether owl:someValuesFrom inferencing is enabled or disabled.
     * @param value {@code true} if owl:someValuesFrom inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferSomeValuesFrom(final Boolean value) {
        Preconditions.checkNotNull(value);
        setBoolean(INFER_INCLUDE_SOME_VALUES_FROM, value);
    }

    /**
     * @return {@code true} if rdfs:subClassOf inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferSubClassOf() {
        return getBoolean(INFER_INCLUDE_SUBCLASSOF, true);
    }

    /**
     * Sets whether rdfs:subClassOf inferencing is enabled or disabled.
     * @param val {@code true} if rdfs:subClassOf inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferSubClassOf(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_SUBCLASSOF, val);
    }

    /**
     * @return {@code true} if rdfs:subPropertyOf inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferSubPropertyOf() {
        return getBoolean(INFER_INCLUDE_SUBPROPOF, true);
    }

    /**
     * Sets whether rdfs:subPropertyOf inferencing is enabled or disabled.
     * @param val {@code true} if rdfs:subPropertyOf inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferSubPropertyOf(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_SUBPROPOF, val);
    }

    /**
     * @return {@code true} if owl:SymmetricProperty inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferSymmetricProperty() {
        return getBoolean(INFER_INCLUDE_SYMMPROP, true);
    }

    /**
     * Sets whether owl:SymmetricProperty inferencing is enabled or disabled.
     * @param val {@code true} if owl:SymmetricProperty inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferSymmetricProperty(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_SYMMPROP, val);
    }

    /**
     * @return {@code true} if owl:TransitiveProperty inferencing is enabled.
     * {@code false} otherwise. Defaults to {@code true} if nothing is
     * specified.
     */
    public Boolean isInferTransitiveProperty() {
        return getBoolean(INFER_INCLUDE_TRANSITIVEPROP, true);
    }

    /**
     * Sets whether owl:TransitiveProperty inferencing is enabled or disabled.
     * @param val {@code true} if owl:TransitiveProperty inferencing is enabled.
     * {@code false} otherwise.
     */
    public void setInferTransitiveProperty(final Boolean val) {
        Preconditions.checkNotNull(val);
        setBoolean(INFER_INCLUDE_TRANSITIVEPROP, val);
    }

    public void setRdfEvalStatsDaoClass(final Class<? extends RdfEvalStatsDAO> rdfEvalStatsDaoClass) {
        Preconditions.checkNotNull(rdfEvalStatsDaoClass);
        setClass(RDF_EVAL_STATS_DAO_CLASS, rdfEvalStatsDaoClass, RdfEvalStatsDAO.class);
    }

    public Class<? extends RdfEvalStatsDAO> getRdfEvalStatsDaoClass() {
        return getClass(RDF_EVAL_STATS_DAO_CLASS, null, RdfEvalStatsDAO.class);
    }


    public void setPcjTables(final List<String> indexTables) {
        Preconditions.checkNotNull(indexTables);
        setStrings(CONF_PCJ_TABLES, indexTables.toArray(new String[]{}));
    }


    public List<String> getPcjTables() {
        final List<String> pcjTables = Lists.newArrayList();
        final String[] tables = getStrings(CONF_PCJ_TABLES);
        if(tables == null) {
            return pcjTables;
        }
        for(final String table: tables) {
            Preconditions.checkNotNull(table);
            pcjTables.add(table);
        }
        return pcjTables;
    }

    public void setUseStatementMetadata(final boolean useMetadata) {
        setBoolean(CONF_USE_STATEMENT_METADATA, useMetadata);
    }

    public boolean getUseStatementMetadata() {
        return getBoolean(CONF_USE_STATEMENT_METADATA, false);
    }

    public void setStatementMetadataProperties(final Set<RyaURI> metadataProperties) {

        final String[] propArray = new String[metadataProperties.size()];
        int i = 0;
        for(final RyaURI uri: metadataProperties) {
            propArray[i] = uri.getData();
            i++;
        }
        setStrings(CONF_STATEMENT_METADATA_PROPERTIES, propArray);
    }


    public Set<RyaURI> getStatementMetadataProperties() {
        final Set<RyaURI> uriSet = new HashSet<>();
        final String[] uriStrings = getStrings(CONF_STATEMENT_METADATA_PROPERTIES);
        if (uriStrings != null) {
            for (final String s : uriStrings) {
                uriSet.add(new RyaURI(s));
            }
        }
        return uriSet;
    }


    public void setPcjOptimizer(final Class<? extends QueryOptimizer> optimizer) {
        Preconditions.checkNotNull(optimizer);
        setClass(CONF_PCJ_OPTIMIZER, optimizer, QueryOptimizer.class);
    }

    public Class<QueryOptimizer> getPcjOptimizer() {
        final Class<? extends QueryOptimizer> opt = getClass(CONF_PCJ_OPTIMIZER, null, QueryOptimizer.class);
        if (opt != null) {
            Preconditions.checkArgument(QueryOptimizer.class.isAssignableFrom(opt));
            return (Class<QueryOptimizer>) opt;
        } else {
            return null;
        }
    }


    public void setOptimizers(final List<Class<? extends QueryOptimizer>> optimizers) {
        Preconditions.checkNotNull(optimizers);
        final List<String> strs = Lists.newArrayList();
        for (final Class ai : optimizers){
            Preconditions.checkNotNull(ai);
            strs.add(ai.getName());
        }

        setStrings(CONF_OPTIMIZERS, strs.toArray(new String[]{}));
    }

    public List<Class<QueryOptimizer>> getOptimizers() {
        final List<Class<QueryOptimizer>> opts = Lists.newArrayList();
        for (final Class<?> clazz : getClasses(CONF_OPTIMIZERS)){
            Preconditions.checkArgument(QueryOptimizer.class.isAssignableFrom(clazz));
            opts.add((Class<QueryOptimizer>) clazz);
        }

        return opts;
    }



    public String getRegexSubject() {
        return get(REGEX_SUBJECT);
    }

    public void setRegexSubject(final String regexSubject) {
        Preconditions.checkNotNull(regexSubject);
        set(REGEX_SUBJECT, regexSubject);
    }

    public String getRegexPredicate() {
        return get(REGEX_PREDICATE);
    }

    public void setRegexPredicate(final String regex) {
        Preconditions.checkNotNull(regex);
        set(REGEX_PREDICATE, regex);
    }

    public String getRegexObject() {
        return get(REGEX_OBJECT);
    }

    public void setRegexObject(final String regex) {
        Preconditions.checkNotNull(regex);
        set(REGEX_OBJECT, regex);
    }
}
