org.topicquests.solr.SolrDataProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.topicquests.solr.SolrDataProvider.java

Source

/*
 * Copyright 2012, TopicQuests
 *
 * Licensed 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.topicquests.solr;

import java.io.Writer;
import java.util.*;
//import java.net.URLEncoder;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.topicquests.common.ResultPojo;
import org.topicquests.common.api.IMergeRuleMethod;
import org.topicquests.common.api.IResult;
import org.topicquests.common.api.ITopicQuestsOntology;
import org.topicquests.solr.api.ISolrClient;
import org.topicquests.solr.api.ISolrDataProvider;
import org.topicquests.util.LoggingPlatform;
import org.topicquests.model.Environment;
import org.topicquests.model.api.INodeModel;
import org.topicquests.model.api.IMergeImplementation;
import org.topicquests.model.api.INode;
import org.topicquests.model.api.ITuple;
import org.topicquests.model.api.ITupleQuery;
import org.topicquests.model.api.IXMLFields;

import org.nex.util.LRUCache;

import org.apache.commons.collections.CollectionUtils;
//use parseDate to get a Date from a Solr date string
//import org.apache.solr.common.util.DateUtil;

/**
 * @author park
 *
 */
public class SolrDataProvider implements ISolrDataProvider {
    private LoggingPlatform log = LoggingPlatform.getLiveInstance();
    private ISolrClient client;
    private INodeModel _model;
    private ITupleQuery tupleQuery;
    private SolrExporter exporter;
    /** We only save public nodes in this cache */
    private LRUCache nodeCache;

    /**
     * @param cacheSize
     * 
     */
    public SolrDataProvider(SolrEnvironment e, int cacheSize) throws Exception {
        client = e.getSolrClient();

        exporter = new SolrExporter(this);
        nodeCache = new LRUCache(cacheSize);
        tupleQuery = new SolrTupleQuery(this);
        //default NO MERGE model
        _model = new SolrNodeModel(this, null);
    }

    @Override
    public void removeFromCache(String nodeLocator) {
        nodeCache.remove(nodeLocator);
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#getUUID()
     */
    public String getUUID() {
        UUID x = UUID.randomUUID();
        return x.toString();
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#getUUID_Pre(java.lang.String)
     */
    public String getUUID_Pre(String prefix) {
        UUID x = UUID.randomUUID();
        return prefix + x.toString();
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#getUUID_Post(java.lang.String)
     */
    public String getUUID_Post(String suffix) {
        UUID x = UUID.randomUUID();
        return x.toString() + suffix;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#getNode(java.lang.String)
     */
    public IResult getNode(String locator, Set<String> credentials) {
        IResult result = null;
        INode n = (INode) nodeCache.get(locator);
        if (n != null) {
            result = new ResultPojo();
            result.setResultObject(n);
        } else {
            result = runQuery(ITopicQuestsOntology.LOCATOR_PROPERTY + ":" + locator, 0, -1, credentials);
            List<INode> l = (List<INode>) result.getResultObject();
            System.out.println("SolrDataProvider.getNode " + locator + " " + l);
            if (l != null && l.size() > 0) {
                n = (INode) l.get(0);
                if (!n.getIsPrivate()) {
                    //if it's public, return it and add to cache
                    result.setResultObject(n);
                    nodeCache.add(locator, n);
                } else {
                    result.setResultObject(testNodeForCredentials(n, credentials)); //That's the result
                    if (result.getResultObject() == null)
                        result.addErrorString("Insufficient credentials for a private node");
                }
            } else
                result.setResultObject(null);
        }
        return result;
    }

    @Override
    public IResult getVirtualNodeIfExists(String locator, Set<String> credentials) {
        String query = ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE + ":"
                + ITopicQuestsOntology.MERGE_ASSERTION_TYPE + " AND " + ITopicQuestsOntology.TUPLE_OBJECT_PROPERTY
                + ":" + locator;
        IResult r = client.runQuery(query, 0, -1);
        log.logDebug("SolrDataProvider.getVirtualNodeIfExists " + query + " | " + r.getResultObject());
        String lox = locator;
        if (r.getResultObject() != null) {
            SolrDocumentList ol = (SolrDocumentList) r.getResultObject();
            if (ol.size() > 0) {
                Map<String, Object> m = (Map<String, Object>) ol.get(0);
                lox = (String) m.get(ITopicQuestsOntology.TUPLE_SUBJECT_PROPERTY);
                log.logDebug("SolrDataProvider.getVirtualNodeIfExists-1 " + locator + " " + lox);
            }
        }
        return getNode(lox, credentials);
    }

    /**
     * Utility method to accept or reject a node based on privacy and credentials
     * @param n
     * @param credentials
     * @return
     */
    INode testNodeForCredentials(INode n, Set<String> credentials) {
        INode result = n;
        if (n.getIsPrivate()) {
            //         System.out.println("XXXX-1");
            List<String> creds = n.listRestrictionCredentials();
            //         System.out.println("testnodeforcredentials-1 "+n.getLocator()+" "+creds+" "+credentials);
            Collection<String> x = CollectionUtils.intersection(credentials, creds);
            if (x.isEmpty())
                result = null;
        }
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#removeNode(java.lang.String)
     */
    public IResult removeNode(String locator) {
        IResult result = new ResultPojo();
        // TODO Auto-generated method stub
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#putNode(org.topicquests.model.api.INode)
     */
    public IResult putNode(INode node) {
        return client.addData(node.getProperties());
    }

    @Override
    public IResult putNodeNoMerge(INode node) {
        return client.addDataNoMerge(node.getProperties());
    }

    /**
     * Utility method to hande a list of nodes
     * @param result
     * @param credentials
     */
    void listNodes(IResult result, Set<String> credentials) {
        List<INode> temp = (List<INode>) result.getResultObject();
        //      System.out.println("SolrDataProvider.listNodes "+temp.size());
        if (temp.size() > 0) {
            //         System.out.println("AAAA");
            List<INode> l = new ArrayList<INode>();
            int len = temp.size();
            //         System.out.println("AAAB "+len);
            INode n;
            for (int i = 0; i < len; i++) {
                //            System.out.println("AAAC "+i);
                n = (INode) temp.get(i);
                //            System.out.println("XXXX "+n.getIsPrivate());
                n = testNodeForCredentials(n, credentials);
                if (n != null)
                    l.add(n);
            }
            result.setResultObject(l);
        }
        //      System.out.println("BBBB");

    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#listNodesByNameString(java.lang.String)
     * /
    public IResult listNodesByNameString(String nameString, Set<String> credentials) {
       IResult result = runQuery(ITopicQuestsOntology.NAME_STRING_PROPERTY,0,-1);
       listNodes(result,credentials);
       return result;
    }
        
    public IResult listNodesByNameStringLike(String nameFragment, int start, int count, Set<String> credentials) {
       String query = ITopicQuestsOntology.NAME_STRING_PROPERTY+":*"+nameFragment+"*";
       IResult result = runQuery(query, start, count);
       listNodes(result,credentials);
       return result;
    }
    */
    /* (non-Javadoc)
     * @see org.topicquests.model.api.INodeModel#listNodesByLabelAndType(java.lang.String, java.lang.String, int, int)
     */
    public IResult listNodesByLabelAndType(String label, String typeLocator, int start, int count,
            Set<String> credentials) {
        String query = ITopicQuestsOntology.LABEL_PROPERTY + ":" + label + " AND "
                + ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE + ":" + typeLocator;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.INodeModel#listNodesByLabel(java.lang.String, int, int)
     */
    public IResult listNodesByLabel(String label, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.LABEL_PROPERTY + ":" + label;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    public IResult listNodesByLabelLike(String labelFragment, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.LABEL_PROPERTY + ":*" + labelFragment + "*";
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    public IResult listNodesByDetailsLike(String detailsFragment, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.DETAILS_PROPERTY + ":*" + detailsFragment + "*";
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.INodeModel#listNodesByQuery(java.lang.String, int, int)
     */
    public IResult listNodesByQuery(String queryString, int start, int count, Set<String> credentials) {
        IResult result = runQuery(queryString, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    public IResult listNodesByCreatorId(String creatorId, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.CREATOR_ID_PROPERTY + ":" + creatorId;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.INodeModel#listNodesByType(java.lang.String, int, int)
     */
    public IResult listNodesByType(String typeLocator, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE + ":" + typeLocator;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    public IResult listInstanceNodes(String typeLocator, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE + ":" + typeLocator;
        System.out.println("LISTINSTANCES- " + query);
        IResult result = runQuery(query, start, count, credentials);
        System.out.println("LISTINSTANCES-1 " + result.hasError() + " " + result.getResultObject());

        listNodes(result, credentials);
        System.out.println("LISTINSTANCES+ " + result.hasError() + " " + result.getResultObject());
        return result;
    }

    @Override
    public IResult listTrimmedInstanceNodes(String typeLocator, int start, int count, Set<String> credentials) {
        // Can be same type AND virtual proxy
        // OR Can be same type AND NOT merged 
        String query = "(" + ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE + ":" + typeLocator + " AND "
                + ITopicQuestsOntology.IS_VIRTUAL_PROXY + ":true) OR " + "("
                + ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE + ":" + typeLocator + " AND NOT "
                + ITopicQuestsOntology.MERGE_TUPLE_PROPERTY + ":* )";// OR "+
        //ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE+":"+typeLocator;
        System.out.println("LISTTRIMMEDINSTANCES- " + query);
        IResult result = runQuery(query, start, count, credentials);
        System.out.println("LISTTRIMMEDINSTANCES-1 " + result.hasError() + " " + result.getResultObject());

        listNodes(result, credentials);
        System.out.println("LISTTRIMMEDINSTANCES+ " + result.hasError() + " " + result.getResultObject());
        return result;
    }

    public IResult listSubclassNodes(String superclassLocator, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.SUBCLASS_OF_PROPERTY_TYPE + ":" + superclassLocator;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.INodeModel#getNodeByPSI(java.lang.String)
     */
    public IResult listNodesByPSI(String psi, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.PSI_PROPERTY_TYPE + ":" + psi;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#putTuple(org.topicquests.model.api.ITuple)
     */
    public IResult putTuple(ITuple tuple) {
        return client.addData(tuple.getProperties());
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#getTuple(java.lang.String)
     */
    public IResult getTuple(String tupleLocator, Set<String> credentials) {
        IResult result = runQuery(ITopicQuestsOntology.LOCATOR_PROPERTY + ":" + tupleLocator, 0, -1, credentials);
        List<INode> l = (List<INode>) result.getResultObject();
        if (l != null && l.size() > 0) {
            ITuple n = (ITuple) l.get(0);
            result.setResultObject(n);
        } else
            result.setResultObject(null);
        return result;
    }

    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#listTuplesByPredTypeAndSubjectId(java.lang.String, java.lang.String)
     * /
    public IResult listTuplesByPredTypeAndSubjectId(String predType,
     String subjectLocator, int start, int count) {
       IResult result = new ResultPojo();
       // TODO Auto-generated method stub
       return result;
    }
        
    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#listTuplesBySubjectId(java.lang.String)
     * /
    public IResult listTuplesBySubjectId(String subjectLocator, int start, int count) {
       IResult result = new ResultPojo();
       // TODO Auto-generated method stub
       return result;
    }
        
    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#listTuplesByPredTypeAndObject(java.lang.String, java.lang.String)
     * /
    public IResult listTuplesByPredTypeAndObject(String predType, String obj, int start, int count) {
       IResult result = new ResultPojo();
       String query = ITopicQuestsOntology.INSTANCE_OF_PROPERTY_TYPE+":"+predType; //TODO
       // TODO Auto-generated method stub
       return result;
    }
        
    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#updateTuple(org.topicquests.model.api.ITuple)
     * /
    public IResult updateTuple(ITuple tuple) {
       IResult result = new ResultPojo();
       // TODO Auto-generated method stub
       return result;
    }
        
    /* (non-Javadoc)
     * @see org.topicquests.model.api.IDataProvider#removeTuple(org.topicquests.model.api.ITuple)
     * /
    public IResult removeTuple(ITuple tuple) {
       IResult result = new ResultPojo();
       // TODO Auto-generated method stub
       return result;
    }
    */
    public ISolrClient getSolrClient() {
        return client;
    }

    public IResult runQuery(String queryString, int start, int count, Set<String> credentials) {
        System.out.println("SolrDataProvider.runQuery " + queryString);
        IResult result = client.runQuery(queryString, start, count);
        result = convertResultsWithFilter(result, credentials);
        return result;
    }

    /**
     * Convert a list of {@link SolrDocument} objects to either {@link INode} or {@link ITuple} objects
     * @param x
     * @return
     */
    IResult convertResults(IResult x) {
        IResult result = new ResultPojo();
        List<INode> l = new ArrayList<INode>();
        result.setResultObject(l);
        SolrDocumentList ol = (SolrDocumentList) x.getResultObject();
        if (ol != null) {
            INode obj;
            Map<String, Object> dx;
            int len = ol.size();
            for (int i = 0; i < len; i++) {
                dx = (Map<String, Object>) ol.get(i);
                unescapeQueryCulprits(dx);
                obj = new Node(dx);
                //System.out.println("QQQQ "+obj.toXML());
                l.add(obj);
            }
        }
        return result;

    }

    void unescapeQueryCulprits(Map<String, Object> map) {
        String key;
        List<String> vals;
        Object o;
        Iterator<String> itr = map.keySet().iterator();
        while (itr.hasNext()) {
            key = itr.next();
            if (key.startsWith(ITopicQuestsOntology.LABEL_PROPERTY)
                    || key.startsWith(ITopicQuestsOntology.DETAILS_PROPERTY)) {
                o = map.get(key);
                if (o != null) {
                    if (o instanceof List) {
                        vals = (List<String>) o;
                        map.put(key, cleanListOfStrings(vals));
                    } else {
                        //REQUIRE that labels and details always be List<String>
                        vals = new ArrayList<String>();
                        vals.add((String) o);
                        map.put(key, cleanListOfStrings(vals));
                    }
                }
            }
        }
    }

    List<String> cleanListOfStrings(List<String> vals) {
        List<String> result = new ArrayList<String>(vals.size());
        String x;
        Iterator<String> itr = vals.iterator();
        while (itr.hasNext()) {
            x = itr.next();
            x = QueryUtil.unEscapeQueryCulprits(x);
            result.add(x);
        }

        return result;
    }

    /**
     * Convert a list of {@link SolrDocument} objects to either {@link INode} or {@link ITuple} object
     * after filtering on <code>credentials</code>
     * @param x
     * @param credentials
     * @return
     */
    IResult convertResultsWithFilter(IResult x, Set<String> credentials) {
        //      System.out.println("CONVERTRESULT- "+x.getResultObject());
        IResult result = new ResultPojo();
        List<INode> l = new ArrayList<INode>();
        result.setResultObject(l);
        SolrDocumentList ol = (SolrDocumentList) x.getResultObject();
        if (ol != null) {
            INode obj;
            Map<String, Object> dx;
            int len = ol.size();
            for (int i = 0; i < len; i++) {
                dx = (Map<String, Object>) ol.get(i);
                if (isSafe(dx, credentials)) {
                    obj = new Node(dx);
                    //System.out.println("QQQQ "+obj.toXML());
                    l.add(obj);
                }
            }
        }
        return result;
    }

    /**
     * Will always return false if private node and <code>credentials = null</code>
     * @param node
     * @param credentials
     * @return
     */
    boolean isSafe(Map<String, Object> node, Set<String> credentials) {
        System.out.println("ISSAFE- " + node.get(ITopicQuestsOntology.LOCATOR_PROPERTY) + " "
                + node.get(ITopicQuestsOntology.IS_PRIVATE_PROPERTY));
        Boolean isPrivate = (Boolean) node.get(ITopicQuestsOntology.IS_PRIVATE_PROPERTY);
        if (isPrivate == null) // rare event; need to understand what's going on
            log.logError("SolrDataProvider.isSafe bad boolean " + node, null);
        else if (isPrivate) {
            if (credentials == null)
                return false;
            Object o = node.get(ITopicQuestsOntology.RESTRICTION_PROPERTY_TYPE);
            if (o == null) {
                //only option is to see if credentials include userId
                String creatorId = (String) node.get(ITopicQuestsOntology.CREATOR_ID_PROPERTY);
                return credentials.contains(creatorId);
            } else {
                List<String> acls = (List<String>) o;
                Collection<String> x = CollectionUtils.intersection(credentials, acls);
                return x.isEmpty();
            }
        }
        return true; // default
    }

    /**
     * Do it by hand now, but later create a custom Solr RequestHandler
     */
    public IResult nodeIsA(String nodeLocator, String targetTypeLocator, Set<String> credentials) {
        IResult result = walkUpTransitiveClosure(nodeLocator, targetTypeLocator, credentials);
        if (result.getResultObject() != null)
            result.setResultObject(new Boolean(true));
        else
            result.setResultObject(new Boolean(false));
        return result;
    }

    /**
     * A recursive call to walk up the isA hierarchy, if any, above the
     * @param locator
     * @param typeTargetLocator
     * @param credentials
     * @return IResult.returnObject = <code>null</code> if not found. Any non-null means found
     */
    IResult walkUpTransitiveClosure(String locator, String typeTargetLocator, Set<String> credentials) {
        IResult result = new ResultPojo();
        result.setResultObject(null);
        IResult temp = getNode(locator, credentials);
        INode child = (INode) temp.getResultObject();
        temp.setResultObject(null);
        if (temp.hasError())
            result.addErrorString(temp.getErrorString());
        if (child != null) {
            //The cases where that could be null are:
            //  database error (node's there, system failed)
            //  lack of appropriate credentials (private node)
            List<String> supers = child.listSuperclassIds();
            String type = child.getNodeType();
            if (type.equals(typeTargetLocator)) {
                result.setResultObject(child);
                return result;
            } else {
                temp = walkUpTransitiveClosure(type, typeTargetLocator, credentials);
                if (temp.hasError())
                    result.addErrorString(temp.getErrorString());
                if (temp.getResultObject() != null) {
                    result.setResultObject(temp.getResultObject());
                    return result;
                }
            }
            if (supers != null && supers.size() > 0) {
                Iterator<String> itr = supers.iterator();
                while (itr.hasNext()) {
                    temp = walkUpTransitiveClosure(itr.next(), typeTargetLocator, credentials);
                    if (temp.hasError())
                        result.addErrorString(temp.getErrorString());
                    if (temp.getResultObject() != null) {
                        result.setResultObject(temp.getResultObject());
                        return result;
                    }
                }
            }
        }
        return result;
    }

    /**
     * Do it by hand now, but later create a custom Solr RequestHandler
     */
    public IResult getNodeView(String locator, Set<String> credentials) {
        IResult result = new ResultPojo();
        // TODO Auto-generated method stub
        return result;
    }

    @Override
    public INodeModel getNodeModel() {
        return _model;
    }

    @Override
    public IResult exportXmlFile(Writer out, Set<String> credentials) {
        return exporter.exportXmlFile(out, credentials);
    }

    @Override
    public IResult exportXmlTreeFile(String treeRootLocator, Writer out, Set<String> credentials) {
        IResult result = null;
        try {
            out.write("<" + IXMLFields.DATABASE + ">\n");
            result = exporter.exportXmlTreeFile(treeRootLocator, out, credentials, true);
            out.write("</" + IXMLFields.DATABASE + ">\n");
            out.flush();
            out.close();
        } catch (Exception e) {
            result.addErrorString(e.getMessage());
            log.logError(e.getMessage(), e);
        }
        return result;
    }

    @Override
    public IResult updateNode(INode node) {
        this.removeFromCache(node.getLocator());
        return client.updateData(node.getProperties());
    }

    @Override
    public IResult partialUpdateData(Map<String, Object> fields) {
        String lox = (String) fields.get(ITopicQuestsOntology.LOCATOR_PROPERTY);
        if (lox == null) {
            IResult result = new ResultPojo();
            result.addErrorString("SolrDataProvider.partialUpdateData missing locator property");
            return result;
        } else {
            this.removeFromCache(lox);
            return client.partialUpdateData(fields);
        }

    }

    @Override
    public ITupleQuery getTupleQuery() {
        return tupleQuery;
    }

    @Override
    public IResult createMergeRule(IMergeRuleMethod theMethod) {
        IResult result = new ResultPojo();
        // TODO Auto-generated method stub
        return result;
    }

    @Override
    public IResult existsTupleBySubjectOrObjectAndRelation(String theLocator, String relationLocator) {
        IResult result = new ResultPojo();
        // TODO Auto-generated method stub
        return result;
    }

    @Override
    public void setMergeBean(IMergeImplementation merger) {
        _model = new SolrNodeModel(this, merger);
    }

    @Override
    public IResult listTuplesBySignature(String signature, int start, int count, Set<String> credentials) {
        String query = ITopicQuestsOntology.TUPLE_SIGNATURE_PROPERTY + ":" + signature;
        IResult result = runQuery(query, start, count, credentials);
        listNodes(result, credentials);
        return result;
    }

    @Override
    public IResult init(Environment env, int cachesize) {
        //NOT USED
        return null;
    }

}