Package com.github.rnewson.couchdb.lucene

Source Code of com.github.rnewson.couchdb.lucene.DocumentConverter

/*
* Copyright Robert Newson
*
* 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 com.github.rnewson.couchdb.lucene;

import com.github.rnewson.couchdb.lucene.couchdb.CouchDocument;
import com.github.rnewson.couchdb.lucene.couchdb.Database;
import com.github.rnewson.couchdb.lucene.couchdb.View;
import com.github.rnewson.couchdb.lucene.couchdb.ViewSettings;
import com.github.rnewson.couchdb.lucene.rhino.JSLog;
import com.github.rnewson.couchdb.lucene.rhino.RhinoDocument;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryparser.classic.ParseException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.javascript.*;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

public final class DocumentConverter {

    private static final Collection<Document> NO_DOCUMENTS = Collections.emptyList();
    private static final Logger LOG = Logger.getLogger(DocumentConverter.class);

    private final Context context;
    private final Function viewFun;
    private final ScriptableObject scope;

    public DocumentConverter(final Context context, final View view) throws IOException, JSONException {
        this.context = context;
        scope = context.initStandardObjects();
        context.setLanguageVersion(Context.VERSION_1_8);

        // Allow custom document helper class.
        try {
            ScriptableObject.defineClass(scope, RhinoDocument.class);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        // Add a log object
        ScriptableObject.putProperty(scope, "log", new JSLog());

        // Compile user-specified function
        try {
            viewFun = view.compileFunction(context, scope);
        } catch (final RhinoException e) {
            LOG.error("View code for " + view + " does not compile.");
            throw e;
        }
    }

    public Collection<Document> convert(
            final CouchDocument doc,
            final ViewSettings defaults,
            final Database database) throws IOException, ParseException, JSONException {
        final Object result;
        final Scriptable scriptable = convertObject(doc.asJson());

        try {
            result = viewFun.call(context, scope, null, new Object[]{scriptable});
        } catch (final JavaScriptException e) {
            LOG.warn(doc + " caused exception during conversion.", e);
            return NO_DOCUMENTS;
        }

        if (result == null || result instanceof Undefined) {
            return NO_DOCUMENTS;
        }

        if (result instanceof RhinoDocument) {
            final RhinoDocument rhinoDocument = (RhinoDocument) result;
            final Document document = rhinoDocument.toDocument(doc.getId(), defaults, database);
            return Collections.singleton(document);
        }

        if (result instanceof NativeArray) {
            final NativeArray nativeArray = (NativeArray) result;
            final Collection<Document> arrayResult = new ArrayList<Document>((int) nativeArray.getLength());
            for (int i = 0; i < (int) nativeArray.getLength(); i++) {
                if (nativeArray.get(i, null) instanceof RhinoDocument) {
                    final RhinoDocument rhinoDocument = (RhinoDocument) nativeArray.get(i, null);
                    final Document document = rhinoDocument.toDocument(
                            doc.getId(),
                            defaults,
                            database);
                    arrayResult.add(document);
                }
            }
            return arrayResult;
        }

        return null;
    }

    private Object convert(final Object obj) throws JSONException {
        if (obj instanceof JSONArray) {
            return convertArray((JSONArray) obj);
        } else if (obj == JSONObject.NULL) {
            return null;
        } else if (obj instanceof JSONObject) {
            return convertObject((JSONObject) obj);
        } else {
            return obj;
        }
    }

    private Scriptable convertArray(final JSONArray array) throws JSONException {
        final Scriptable result = context.newArray(scope, array.length());
        for (int i = 0, max = array.length(); i < max; i++) {
            ScriptableObject.putProperty(result, i, convert(array.get(i)));
        }
        return result;
    }

    private Scriptable convertObject(final JSONObject obj) throws JSONException {
        if (obj == JSONObject.NULL) {
            return null;
        }
        final Scriptable result = context.newObject(scope);
        final Iterator<?> it = obj.keys();
        while (it.hasNext()) {
            final String key = (String) it.next();
            final Object value = obj.get(key);
            ScriptableObject.putProperty(result, key, convert(value));
        }
        return result;
    }

}
TOP

Related Classes of com.github.rnewson.couchdb.lucene.DocumentConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.