Package diametric

Source Code of diametric.DiametricUtils

package diametric;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBignum;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyHash;
import org.jruby.RubyNil;
import org.jruby.RubyString;
import org.jruby.RubySymbol;
import org.jruby.RubyTime;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.javasupport.JavaUtil;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import clojure.lang.APersistentMap;
import clojure.lang.APersistentVector;
import clojure.lang.IPersistentSet;
import clojure.lang.Keyword;
import clojure.lang.LazySeq;
import clojure.lang.PersistentHashSet;
import clojure.lang.PersistentVector;
import clojure.lang.Var;
import datomic.Util;

@JRubyModule(name="Diametric::Persistence::Utils")
public class DiametricUtils {

    @JRubyMethod(meta=true)
    public static IRubyObject read_all(ThreadContext context, IRubyObject klazz, IRubyObject arg) {
        String filename = null;
        if (arg instanceof RubyString) {
            filename = DiametricUtils.rubyStringToJava(arg);
        } else {
            throw context.getRuntime().newArgumentError("Argument should be filename");
        }
        Reader reader = null;
        try {
            reader = new FileReader(filename);
            List list = (List) Util.readAll(reader);
            RubyArray array = RubyArray.newArray(context.getRuntime(), list.size());
            array.addAll(list);
            return array;
        } catch (Exception e) {
            throw context.getRuntime().newRuntimeError(e.getMessage());
        } finally {
            try {
                if (reader != null) reader.close();
            } catch (IOException e) {
                // no-op
            }
        }
    }

    @JRubyMethod(meta=true)
    public static IRubyObject read_string(ThreadContext context, IRubyObject klazz, IRubyObject arg) {
        if (!(arg instanceof RubyString)) {
            throw context.getRuntime().newArgumentError("Argument should be string");
        }
        RubyString ruby_string = (RubyString)arg;
        try {
            Var reader = DiametricService.getFn("clojure.core", "read-string");
            Object value = reader.invoke((String)ruby_string.asJavaString());
            RubyClass clazz = (RubyClass)context.getRuntime().getClassFromPath("Diametric::Persistence::Object");
            DiametricObject diametric_object = (DiametricObject)clazz.allocate();
            diametric_object.update(value);
            return diametric_object;
        } catch (Exception e) {
            throw context.getRuntime().newRuntimeError(e.getMessage());
        }
    }

    @JRubyMethod(meta=true, required=1, rest=true)
    public static IRubyObject fn(ThreadContext context, IRubyObject klazz, IRubyObject args[]) {
        try {
            Var list_fn = DiametricService.getFn("clojure.core", "list");
            List list = (List) list_fn.invoke();
            Var cons_fn = DiametricService.getFn("clojure.core", "conj");
            Var read_string_fn = DiametricService.getFn("clojure.core", "read-string");
            for (int i=args.length-1; i>-1; i--) {
                Object value = DiametricUtils.convertRubyToJava(context, args[i]);
                if (value instanceof RubyString) {
                    value = read_string_fn.invoke(value);
                }
                list = (List) cons_fn.invoke(list, value);
            }
            RubyClass clazz = (RubyClass)context.getRuntime().getClassFromPath("Diametric::Persistence::Fn");
            DiametricFn diametric_fn = (DiametricFn)clazz.allocate();
            diametric_fn.init(list);
            return diametric_fn;
        } catch (Throwable t) {
            throw context.getRuntime().newArgumentError(t.getMessage());
        }
    }

    static String rubyStringToJava(IRubyObject arg) {
        if (arg instanceof RubyString) {
            // TODO probably, we need to specify encoding.
            return (String) ((RubyString)arg).toJava(String.class);
        } else {
            return null;
        }
    }

    static Object convertRubyToJava(ThreadContext context, IRubyObject value) {
        if (value instanceof RubyNil) return null;
        if (value instanceof RubyString) {
            String str = (String)((RubyString)value).toJava(String.class);
            return getStringOrUUID(str);
        }
        if (value instanceof RubyBoolean) return (Object)((RubyBoolean)value).toJava(Boolean.class);
        if (value instanceof RubyFixnum) return (Object)((RubyFixnum)value).toJava(Long.class);
        if (value instanceof DiametricUUID) return ((DiametricUUID)value).getUUID();
        if (value instanceof RubyBignum) {
            RubyString svalue = (RubyString)((RubyBignum)value).to_s();
            java.math.BigInteger bivalue = new java.math.BigInteger((String)svalue.toJava(String.class));
            return (Object)bivalue;
        }
        if (value instanceof RubyFloat) return (Object)((RubyFloat)value).toJava(Double.class);
        if (value instanceof RubyTime) {
            RubyTime tmvalue = (RubyTime)value;
            return (Object)tmvalue.getJavaDate();
        }
        if (value instanceof RubySymbol) {
            // schema or data keyword
            RubyString edn_string = (RubyString)RuntimeHelpers.invoke(context, value, "to_s");
            return (Object)Keyword.intern((String)edn_string.asJavaString());
        }
        if (value.respondsTo("to_edn") && value.respondsTo("symbol")) {
            // EDN::Type::Symbol (query)
            RubyString edn_string = (RubyString)RuntimeHelpers.invoke(context, value, "to_edn");
            return (Object)clojure.lang.Symbol.intern((String)edn_string.asJavaString());
        }
        if (value.respondsTo("to_time")) {
            // DateTime or Date
            RubyTime tmvalue = (RubyTime)RuntimeHelpers.invoke(context, value, "to_time");
            return (Object)tmvalue.getJavaDate();
        }
        // needs to check Set since Set responses to "to_a"
        if (value.respondsTo("intersection")) {
            return getPersistentSet(context, value);
        }
        //System.out.println("NOT YET CONVERTED");
        //System.out.println("RESPONDSTO? TO_A:" + value.respondsTo("to_a"));
        //if (value.respondsTo("to_a")) { // might be Set for cardinality many type
        //    return getList(context, value);
        //}
        if (value instanceof DiametricObject) {
            return ((DiametricObject)value).toJava();
        }
        if (value instanceof DiametricFn) {
            return ((DiametricFn)value).toJava();
        }
        if (value instanceof DiametricFunction) {
            return ((DiametricFunction)value).toJava();
        }
        return (Object)value.toJava(Object.class);
    }

    static Object getStringOrUUID(String str) {
        try {
            return (Object)UUID.fromString(str);
        } catch (IllegalArgumentException e) {
            return (Object)str;
        }
    }

    static IPersistentSet getPersistentSet(ThreadContext context, IRubyObject value) {
        return PersistentHashSet.create((List)value.callMethod(context, "to_a"));
    }

    static List<Object> getList(ThreadContext context, IRubyObject value) {
        RubyArray ruby_array = (RubyArray)RuntimeHelpers.invoke(context, value, "to_a");
        List<Object> list = new ArrayList<Object>();
        while (true) {
            IRubyObject element = ruby_array.shift(context);
            if (element.isNil()) break;
            list.add(DiametricUtils.convertRubyToJava(context, element));
        }
        return Collections.unmodifiableList(list);
    }

    static IRubyObject convertJavaToRuby(ThreadContext context, Object value) {
        Ruby runtime = context.getRuntime();
        if (value == null) return context.getRuntime().getNil();
        if (value instanceof String) return RubyString.newString(runtime, (String)value);
        if (value instanceof Boolean) return RubyBoolean.newBoolean(runtime, (Boolean)value);
        if (value instanceof Long) return RubyFixnum.newFixnum(runtime, (Long)value);
        if (value instanceof clojure.lang.Keyword) {
            return RubyString.newString(runtime, ((clojure.lang.Keyword)value).toString());
        }
        if (value instanceof java.math.BigInteger) return RubyBignum.newBignum(runtime, ((java.math.BigInteger)value).longValue());
        if (value instanceof Double) return RubyFloat.newFloat(runtime, (Double)value);
        if (value instanceof Date) return RubyTime.newTime(runtime, ((Date)value).getTime());
        if (value instanceof Set) {
            return DiametricSet.getDiametricSet(context, (Set)value);
        }
        if ((value instanceof APersistentVector) ||
                (value instanceof LazySeq) ||
                (value instanceof PersistentVector.ChunkedSeq)){
            return DiametricCollection.getDiametricCollection(context, (List)value);
        }
        if (value instanceof datomic.Entity) {
            return DiametricEntity.getDiametricEntity(context, value);
        }
        if (value instanceof java.util.UUID) {
            return DiametricUUID.getDiametricUUID(context, (java.util.UUID)value);
        }
        return JavaUtil.convertJavaToUsableRubyObject(runtime, value);
    }

    static PersistentVector convertRubyTxDataToJava(ThreadContext context, IRubyObject arg) {
        if (arg instanceof RubyArray) {
            return fromRubyArray(context, (RubyArray)arg);
        } else {
            Object obj = arg.toJava(Object.class);
            if (obj instanceof clojure.lang.PersistentVector) {
                return (clojure.lang.PersistentVector)obj;
            }
        }
        return null;
    }

    static PersistentVector fromRubyArray(ThreadContext context, RubyArray ruby_array) {
        Var var = DiametricService.getFn("clojure.core", "vector");
        PersistentVector clj_tx_data = (PersistentVector)var.invoke();
        Var adder = DiametricService.getFn("clojure.core", "conj");
        for (int i=0; i<ruby_array.getLength(); i++) {
            Object element = ruby_array.get(i);
            if (element instanceof RubyHash) {
                APersistentMap map = fromRubyHash(context, (RubyHash)element);
                clj_tx_data = (PersistentVector)adder.invoke(clj_tx_data, map);
            } else if (element instanceof RubyArray) {
                PersistentVector vector = fromRubyArray(context, (RubyArray)element);
                clj_tx_data = (PersistentVector)adder.invoke(clj_tx_data, vector);
            } else if (element instanceof IRubyObject) {
                clj_tx_data =
                        (PersistentVector)adder.invoke(clj_tx_data, DiametricUtils.convertRubyToJava(context, (IRubyObject)element));
            } else if (element instanceof String) {
                clj_tx_data = (PersistentVector)adder.invoke(clj_tx_data, getStringOrUUID((String)element));
            } else {
                clj_tx_data = (PersistentVector)adder.invoke(clj_tx_data, element);
            }
        }
        return clj_tx_data;
    }

    private static APersistentMap fromRubyHash(ThreadContext context, RubyHash ruby_hash) {
        Var var = DiametricService.getFn("clojure.core", "hash-map");
        APersistentMap map = (APersistentMap)var.invoke();
        Var associator = DiametricService.getFn("clojure.core", "assoc");
        while (true) {
            IRubyObject pair = ruby_hash.shift(context);
            if (pair instanceof RubyNil) break;
            Object key = DiametricUtils.convertRubyToJava(context, ((RubyArray) pair).shift(context));
            Object value = DiametricUtils.convertRubyToJava(context, ((RubyArray) pair).shift(context));
            if (value instanceof RubyHash) {
                value = fromRubyHash(context, (RubyHash)value);
            } else if (value instanceof RubyArray) {
                value = fromRubyArray(context, (RubyArray)value);
            }
            map = (APersistentMap)associator.invoke(map, key, value);
        }
        return map;
    }
}
TOP

Related Classes of diametric.DiametricUtils

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.