Package net.jcores.jre.cores

Source Code of net.jcores.jre.cores.CoreObject

/*
* CoreObject.java
*
* Copyright (c) 2010, Ralf Biedert All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package net.jcores.jre.cores;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.jcores.jre.CommonCore;
import net.jcores.jre.annotations.SupportsOption;
import net.jcores.jre.cores.adapter.AbstractAdapter;
import net.jcores.jre.cores.adapter.ArrayAdapter;
import net.jcores.jre.cores.adapter.CollectionAdapter;
import net.jcores.jre.cores.adapter.EmptyAdapter;
import net.jcores.jre.cores.adapter.ListAdapter;
import net.jcores.jre.interfaces.functions.F0;
import net.jcores.jre.interfaces.functions.F1;
import net.jcores.jre.interfaces.functions.F1Object2Bool;
import net.jcores.jre.interfaces.functions.F2DeltaObjects;
import net.jcores.jre.interfaces.functions.F2ReduceObjects;
import net.jcores.jre.interfaces.functions.Fn;
import net.jcores.jre.managers.ManagerDebugGUI;
import net.jcores.jre.managers.ManagerDeveloperFeedback;
import net.jcores.jre.options.Args;
import net.jcores.jre.options.InvertSelection;
import net.jcores.jre.options.KillSwitch;
import net.jcores.jre.options.MapType;
import net.jcores.jre.options.MessageType;
import net.jcores.jre.options.Option;
import net.jcores.jre.utils.Async;
import net.jcores.jre.utils.Async.Queue;
import net.jcores.jre.utils.internal.Objects;
import net.jcores.jre.utils.internal.Options;
import net.jcores.jre.utils.internal.Streams;
import net.jcores.jre.utils.internal.processing.Folder;
import net.jcores.jre.utils.internal.processing.Mapper;
import net.jcores.jre.utils.internal.wrapper.Wrapper;
import net.jcores.jre.utils.map.Compound;

/**
* <i>The</i> base class for all other cores that provides basic functions
* like <code>map()</code>, <code>slice()</code>, and many more; give it a look. For example,
* to get the last three elements of an array of Strings, write:<br/>
* <br/>
*
* <code>$(strings).slice(-3, 3).array(String.class)</code><br/>
* <br/>
*
* If you implement your own core you should extend this class.<br/>
* <br/>
*
* A core is immutable. No method will ever change its content array (it is, however,
* possible, that the individual elements enclosed might change).
*
* @author Ralf Biedert
* @since 1.0
*
* @param <T> Type of the objects to wrap.
*/
public class CoreObject<T> extends Core implements Iterable<T> {

    /** */
    private static final long serialVersionUID = -6436821141631907999L;

    /** The adapter we work on */
    protected final AbstractAdapter<T> adapter;

    /**
     * Creates the core object for the given single object.
     *
     * @param supercore CommonCore to use.
     * @param type Type of the object to wrap (in case it is null).
     * @param object Object to wrap.
     */
    @SuppressWarnings("unchecked")
    public CoreObject(CommonCore supercore, Class<?> type, T object) {
        super(supercore);

        // Check if we have an object. If not, and if there is no type, use an
        // empty Object array
        if (object != null) {
            this.adapter = new ArrayAdapter<T>(object);
        } else {
            this.adapter = new EmptyAdapter<T>();
        }
    }

    /**
     * Creates the core object for the given array.
     *
     * @param supercore CommonCore to use.
     * @param objects Object to wrap.
     */
    public CoreObject(CommonCore supercore, T... objects) {
        super(supercore);
        this.adapter = new ArrayAdapter<T>(objects);
    }

    /**
     * Creates the core object for the given array.
     *
     * @param supercore CommonCore to use.
     * @param objects Object to wrap.
     */
    public CoreObject(CommonCore supercore, List<T> objects) {
        super(supercore);

        if (objects instanceof ArrayList) {
            this.adapter = new ListAdapter<T>(objects);
        } else {
            this.adapter = new CollectionAdapter<T, T>(objects);
        }
    }

    /**
     * Creates the core object for the given array.
     *
     * @param supercore CommonCore to use.
     * @param objects Object to wrap.
     */
    public CoreObject(CommonCore supercore, Collection<T> objects) {
        super(supercore);

        if (objects instanceof ArrayList) {
            this.adapter = new ListAdapter<T>((List<T>) objects);
        } else {
            this.adapter = new CollectionAdapter<T, T>(objects);
        }
    }

    /**
     * Creates the core object for the given array.
     *
     * @param supercore CommonCore to use.
     * @param core Core to wrap.
     */
    public CoreObject(CommonCore supercore, CoreObject<T> core) {
        super(supercore);
        this.adapter = core.adapter;
    }

    /**
     * Creates the core object for the given adapter. This is the main constructor each
     * subclass <b>must</b> implement, otherwise <code>object.as()</code> will not work.
     *
     * @param supercore CommonCore to use.
     * @param adapter The adapter to wrap.
     */
    public CoreObject(CommonCore supercore, AbstractAdapter<T> adapter) {
        super(supercore);
        this.adapter = adapter;
    }

    /**
     * Returns a core containing all elements of this core and the other core.
     * Elements that are in both cores will appear twice.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b").add($("c"))</code> - The resulting core contains <code>a</code>, <code>b</code> and
     * <code>c</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param toAdd The core to add to this core.
     *
     * @return A CoreObject containing all objects of this core and the other
     * core.
     */
    @SuppressWarnings("unchecked")
    public CoreObject<T> add(CoreObject<T> toAdd) {
        if (size() == 0) return toAdd;
        if (toAdd.size() == 0) return this;

        Class<?> clazz = this.adapter.clazz();

        final T[] copy = (T[]) Array.newInstance(clazz, size() + toAdd.size());
        final Object[] a = this.adapter.array(clazz);
        final Object[] b = toAdd.adapter.array(clazz);

        System.arraycopy(a, 0, copy, 0, a.length);
        System.arraycopy(b, 0, copy, a.length, b.length);

        return new CoreObject<T>(this.commonCore, copy);
    }

    /**
     * Returns a core containing all elements of this core and the other array.
     * Elements that are in both will appear twice.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b").add("c")</code> - The resulting core contains <code>a</code>, <code>b</code> and
     * <code>c</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param toAdd The array to add to this core.
     *
     * @return A CoreObject containing all objects of this core and the other
     * array.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public CoreObject<T> add(T... toAdd) {
        return this.add(new CoreObject(this.commonCore, toAdd));
    }

    /**
     * Returns the core's content as an array of the given type. Elements that don't fit
     * into the given target type will be skipped.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(list).array(String.class)</code> - Returns a String array for the given list. Elements that are no
     * String will be returned as null.</li>
     * </ul>
     *
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param in Type of the target array to use.
     * @param <N> Type of the array.
     *
     * @return An array containing the all assignable elements.
     */
    public <N> N[] array(Class<N> in) {
        return this.adapter.array(in);
    }

    /**
     * Returns a core that tries to treat all elements as being of the given type.
     * Elements which don't match are ignored. Can also be used to load extensions
     * (e.g., <code>somecore.as(CoreString.class)</code>). This function should not
     * be called within hot-spots (functions called millions of times a second)
     * as it relies heavily on reflection.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(objects).as(MyExtensionCore.class).method()</code> - If you wrote a jCores extension this is how you
     * could activate the extension for a given set of objects and execute one of its methods.</li>
     * <li><code>$("a", null, "c").compact().as(CoreString.class)</code> - Sometimes you call methods from a parent Core
     * (like <code>compact()</code>, which is part of CoreObject, not of {@link CoreString}) that does returns a more
     * general return type then what you want. Using <code>as()</code> you can cast the Core back.</li>
     * </ul>
     *
     *
     * Single-threaded. Heavyweight.<br/>
     * <br/>
     *
     * @param <C> Type of the clazz.
     * @param clazz Core to be spawned and returned.
     * @return If successful, spawns a core of type <code>clazz</code> and returns it,
     * wrapping all contained elements.
     */
    @SuppressWarnings({ "unchecked", "null" })
    public <C extends Core> C as(Class<C> clazz) {
        try {
            final Constructor<?>[] constructors = clazz.getConstructors();
            Constructor<C> constructor = null;

            // Find a proper constructor!
            for (Constructor<?> c : constructors) {
                if (c.getParameterTypes().length != 2) continue;
                if (!c.getParameterTypes()[0].equals(CommonCore.class)) continue;
                if (!c.getParameterTypes()[1].equals(AbstractAdapter.class)) continue;

                // Sanity check.
                if (constructor != null)
                    System.err.println("There should only be one constructor with (CommonCore.class, AbstractAdapter.class) per core! And here comes your exception ... ;-)");

                constructor = (Constructor<C>) c;
            }

            return constructor.newInstance(this.commonCore, this.adapter);

            // NOTE: We do not swallow all execptions, because as() is a bit special and
            // we cannot return anything that would still be usable.
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            this.commonCore.report(MessageType.EXCEPTION, "No constructor found for " + clazz);
            System.err.println("No suitable constructor found!");
        }

        return null;
    }

    /**
     * Performs an asynchronous map operation on this core. The order in which
     * the objects are being mapped is not defined.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$(names).async(lookup)</code> - Performs an asynchronous lookup for the set of names.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param f The function to execute asynchronously on the enclosed objects.
     * @param options The supported options, esp. {@link KillSwitch}.
     * @param <R> Return type for the {@link Async} object.
     * @return An {@link Async} object that will hold the results (in an arbitrary order).
     */
    @SupportsOption(options = { KillSwitch.class })
    public <R> Async<R> async(final F1<T, R> f, Option... options) {
        final Queue<R> queue = Async.Queue();
        final Async<R> async = new Async<R>(this.commonCore, queue);
        final Options options$ = Options.$(this.commonCore, options);
        final KillSwitch killswitch = options$.killswitch();

        this.commonCore.sys.oneTime(new F0() {
            @Override
            public void f() {
                try {
                    // Now process all elements
                    for (T t : CoreObject.this) {
                        // Check if we should terminate.
                        if(killswitch != null && killswitch.terminated())  return;
                       
                        // Otherwise process next element.
                        try {
                            queue.add(Async.QEntry(f.f(t)));
                        } catch (Exception e) {
                            CoreObject.this.commonCore.report(MessageType.EXCEPTION, "Exception when processing " + t + " ... " + e.getMessage());
                            options$.failure(t, e, "for/f", "Unknown exception when processing element");
                        }
                    }
                } finally {
                    // When we're done, close the queue.
                    queue.close();
                }
            }
        }, 0, options);

        return async;

    }

    /**
     * Casts all elements to the given type or sets them null if they are not castable.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$(object).cast(String.class).get(0)</code> - Same as <code>(object instanceof
     * String) ? (String) object : null</code>.</li>
     * </ul>
     *
     * Multi-threaded. <br/>
     * <br/>
     *
     * @param <N> Target type.
     * @param target Class to cast all elements
     * @return A CoreObject wrapping all cast elements.
     */
    public <N> CoreObject<N> cast(final Class<N> target) {
        return map(new F1<T, N>() {
            @SuppressWarnings("unchecked")
            @Override
            public N f(T x) {
                if (target.isAssignableFrom(x.getClass())) return (N) x;
                return null;
            }
        }, MapType.TYPE(target));
    }

    /**
     * Performs a generic call on each element of this core (for
     * example <code>core.call("toString()")</code>), or returns a field (for
     * example <code>core.call("field")</code>). The return values will
     * be stored in a {@link CoreObject}. This is a dirty but shorthand way
     * to call the same function on objects that don't share a common superclass. Should not be
     * called within hot-spots (functions called millions of times a second) as it relies heavily on reflection.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$(tA, tB, tC, tD).call("method()").unique().size()</code> - Calls a method <code>method()</code> on
     * some objects that have no common supertype (except {@link Object}), and returns the number of distinct objects
     * returned</li>
     * <li><code>$(tA, tB, tC, tD).call("field")</code> - Gets the value of the field <code>field</code> on each of the
     * elements, and returns a core with the results.</li>
     * </ul>
     *
     * Multi-threaded. Heavyweight.<br/>
     * <br/>
     *
     * @param string The call to perform, e.g. <code>toString</code>
     * @param params Parameters the call takes
     *
     * @return A CoreObject wrapping the results of each invocation.
     */
    @SuppressWarnings("null")
    public CoreObject<Object> call(final String string, final Object... params) {
        final int len = params == null ? 0 : params.length;
        final Class<?>[] types = new Class[len];
        final CommonCore cc = this.commonCore;

        // Convert classes.
        for (int i = 0; i < len; i++) {
            types[i] = params[i].getClass();
        }

        final boolean methodcall = string.endsWith("()");
        final String call = methodcall ? string.substring(0, string.length() - 2) : string;

        // If this is a method call ...
        if (methodcall) { return map(new F1<T, Object>() {
            public Object f(T x) {
                try {
                    final Method method = x.getClass().getDeclaredMethod(call, types);
                    method.setAccessible(true);
                    return method.invoke(x, params);
                } catch (SecurityException e) {
                    cc.report(MessageType.EXCEPTION, "SecurityException for " + x + " (method was " + string + ")");
                } catch (NoSuchMethodException e) {
                    cc.report(MessageType.EXCEPTION, "NoSuchMethodException for " + x + " (method was " + string + ")");
                } catch (IllegalArgumentException e) {
                    cc.report(MessageType.EXCEPTION, "IllegalArgumentException for " + x + " (method was " + string + ")");
                } catch (IllegalAccessException e) {
                    cc.report(MessageType.EXCEPTION, "IllegalAccessException for " + x + " (method was " + string + ")");
                } catch (InvocationTargetException e) {
                    cc.report(MessageType.EXCEPTION, "InvocationTargetException for " + x + " (method was " + string + ")");
                }

                return null;
            }
        }); }

        // Or a field access
        return map(new F1<T, Object>() {
            public Object f(T x) {
                try {
                    final Field field = x.getClass().getDeclaredField(call);
                    field.setAccessible(true);
                    return field.get(x);
                } catch (SecurityException e) {
                    cc.report(MessageType.EXCEPTION, "SecurityException for " + x + " (method was " + string + ")");
                } catch (IllegalArgumentException e) {
                    cc.report(MessageType.EXCEPTION, "IllegalArgumentException for " + x + " (method was " + string + ")");
                } catch (IllegalAccessException e) {
                    cc.report(MessageType.EXCEPTION, "IllegalAccessException for " + x + " (method was " + string + ")");
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
    }

    /**
     * Serializes this core into the given file. Objects that are not serializable
     * are ignored. The file can later be restored with the function <code>deserialize()</code> in {@link CoreFile}.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("Hello", "World").serialize("data.ser")</code> - Writes the core to a file.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param path The location to which this core should be serialized.
     * @param options Currently not used.
     * @return This core.
     */
    @SupportsOption(options = {})
    public CoreObject<T> serialize(final String path, Option... options) {
        try {
            Streams.serializeCore(this, new FileOutputStream(new File(path)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * For each of the contained elements an object of the type <code>wrapper</code> is
     * being created with the element passed as the first argument to the constructor. If the element is
     * already of the type <code>wrapper</code>, nothing is being done for that element.<br/>
     * <br/>
     *
     * Single-threaded. Heavyweight.<br/>
     * <br/>
     *
     * @param wrapper The class to spawn for each element.
     * @param <W> The type of the wrapper.
     *
     * @return A {@link CoreObject} with the wrapped objects. Elements which could not be wrapped are set to
     * <code>null</code>.
     */
    public <W> CoreObject<W> wrap(final Class<W> wrapper) {
        @SuppressWarnings("unchecked")
        final CoreClass<W> w = new CoreClass<W>(this.commonCore, wrapper);

        return forEach(new F1<T, W>() {
            @SuppressWarnings("unchecked")
            @Override
            public W f(T x) {
                // Check if the object is already assignable
                if (wrapper.isAssignableFrom(x.getClass())) return (W) x;

                return w.spawn(Args.WRAP(x)).get(0);
            }
        });
    }

    /**
     * Return a CoreClass for all enclosed objects' classes.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(o1, o2).clazz()</code> - Wraps the classes for <code>o1</code> and <code>o2</code> in a
     * {@link CoreClass}.</li>
     * </ul>
     *
     * Multi-threaded. <br/>
     * <br/>
     *
     * @return A new {@link CoreClass} containing the classes for all objects.
     */
    @SuppressWarnings("unchecked")
    public CoreClass<T> clazz() {
        return new CoreClass<T>(this.commonCore, map(new F1<T, Class<T>>() {
            @Override
            public Class<T> f(T x) {
                return (Class<T>) x.getClass();
            }
        }).array(Class.class));
    }

    /**
     * Returns a compacted core whose underlying array does not
     * contain null anymore, therefore the positions of elements will be moved to the left to
     * fill null values.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", null, "b").compact()</code> - Returns a core that only contains the elements <code>a</code> and
     * <code>b</code> and has a size of <code>2</code> (the original core also contains <code>null</code> and has a size
     * of <code>3</code>).</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return A new CoreObject of the same type, with a (probably) reduced size without
     * any null element.
     */
    public CoreObject<T> compact() {
        // No size == no fun.
        if (size() == 0) return this;

        final T[] tmp = this.adapter.array();
        int dst = 0;

        for (T element : this) {
            if (element == null) continue;
            tmp[dst++] = element;
        }

        return new CoreObject<T>(this.commonCore, new ArrayAdapter<T>(dst, tmp));
    }

    /**
     * Creates a {@link Compound} out of this core's content. A Compound is a String -> Object
     * map, which is useful for quickly creating complex objects which should be handled by the
     * framework.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("name", name, "age", age).compound()</code> - Quickly creates an untyped {@link Compound} with the
     * keys <code>name</code> and <code>age</code> and the corresponding values.</li>
     * </ul>
     *
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return A new {@link Compound} with this core's content.
     */
    public Compound compound() {
        return Compound.create(this.adapter.array());
    }

    /**
     * Returns true if this core contains the given object. An object is contained if there is
     * another object in this core that is equal to it. <br/>
     * <br/>
     *
     * Note that on a {@link CoreString} this method
     * does <b>not behave as</b> <code>String.contains()</code> (which checks for substrings).
     * If you want to do a substring search, use <code>CoreString.containssubstr()</code>.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(a, b, c, d).contains(c)</code> - Returns <code>true</code>.</li>
     * <li><code>$("aa", "bb", "cc").contains("bb")</code> - Returns <code>true</code>.</li>
     * <li><code>$("aa", "bb", "cc").contains("b")</code> - Returns <b><code>false</code></b>!</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param object The object to search for.
     * @return True if the object is there, false if not.
     */
    public boolean contains(final T object) {
        for (T next : this) {
            if (next != null && next.equals(object)) return true;
            if (next == null && object == null) return true;
        }

        return false;
    }

    /**
     * Counts how many times each unique item is contained in this core (i.e., computes a
     * histogram). <br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "a", "b").contains().value("a")</code> - Returns 2.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return A CoreMap with the counts for each unique object.
     */
    @SuppressWarnings("boxing")
    public CoreMap<T, Integer> count() {
        final Map<T, Integer> results = new HashMap<T, Integer>();

        // Now generate the histogram.
        for (T e : this) {
            if (e == null) continue;

            if (results.containsKey(e)) {
                results.put(e, results.get(e) + 1);
            } else {
                results.put(e, 1);
            }
        }

        // Eventually return the results
        return new CoreMap<T, Integer>(this.commonCore, Wrapper.convert(results));
    }

    /**
     * Prints debug output to the console. Useful for figuring out what's going wrong in a
     * chain of map() operations.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>...somecore.debug().map(f).debug()... </code> - Typical pattern to figure out why a function (
     * <code>map()</code> in this case) might go wrong.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return This object again.
     */
    @SuppressWarnings("unused")
    public CoreObject<T> debug() {

        // Print the result
        System.out.println(fingerprint(false));

        // And add it to the debug GUI
        ManagerDebugGUI debugGUI = this.commonCore.manager(ManagerDebugGUI.class);

        return this;
    }

    /**
     * Returns a core of length size() - 1 consisting of the results of the delta
     * function. Delta always takes two adjacent elements and execute stores the
     * delta function's output. In contrast to the common map operation this function
     * does not ignore <code>null</code> elements. If of two adjacent slots any
     * is <code>null</code>, the value <code>null</code> will be stored. <br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").delta(joiner)</code> - If the given delta function joins two elements then the
     * resulting core contains <code>"ab"</code> and <code>"bc"</code>.</li>
     * </ul>
     *
     * Multi-threaded. <br/>
     * <br/>
     *
     * @param delta The delta function, taking two elements and return a result.
     * @param <R> Type of the result.
     * @param options Relevant options, especiall {@link MapType}.
     *
     * @return A core of size n - 1 containing all deltas.
     */
    @SuppressWarnings("unchecked")
    @SupportsOption(options = { MapType.class })
    public <R> CoreObject<R> delta(final F2DeltaObjects<T, R> delta, Option... options) {
        // Create mapper
        final int size = size();
        final Mapper<T, R> mapper = new Mapper<T, R>(this, options) {
            @Override
            public void handle(int i) {
                // We don't handle the last iteration
                if (i == size - 1) return;

                // Get our target-array (if it is already there)
                R[] a = this.returnArray.get();

                // Get the in-value from the source-array
                final T ii = CoreObject.this.adapter.get(i);
                final T jj = CoreObject.this.adapter.get(i + 1);

                // Convert
                if (ii == null || jj == null) return;

                final R out = delta.f(ii, jj);

                if (out == null) return;

                // If we haven't had an in-array, create it now, according to the return type
                if (a == null) {
                    a = updateReturnArray((R[]) Array.newInstance(out.getClass(), size));
                }

                // Eventually set the out value
                a[i] = out;
            }
        };

        // Map ...
        map(mapper, options);

        // ... and return result.
        return new CoreObject<R>(this.commonCore, new ArrayAdapter<R>(size - 1, mapper.getFinalReturnArray()));

    }

    /**
     * Returns a single object that, if any of its functions is executed, the
     * corresponding function is executed on all enclosed elements. Only works
     * if <code>c</code> is an interface and only on enclosed elements implementing <code>c</code>. From a performance
     * perspective this method only makes sense
     * if the requested operation is complex, as on simple methods the reflection
     * costs will outweigh all benefits. Also note that all return values are skipped. <br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(x1, x2, x3, x4, x5).each(XInterface.class).x()</code> - Given all objects implement
     * <code>XInterface</code> the function <code>each()</code> returns a new <code>X</code> object that, when
     * <code>x()</code> is executed on it, the function is executed on all enclosed objects in parallel.</li>
     * </ul>
     *
     * Multi-threaded. Heavyweight.<br/>
     * <br/>
     *
     * @param c The interface to use.
     * @param <X> The interface's type.
     *
     * @return Something implementing c that acts on each element implementing c.
     */
    @SuppressWarnings("unchecked")
    public <X> X each(final Class<X> c) {
        if (c == null || !c.isInterface()) {
            System.err.println("You must pass an interface.");
            return null;
        }

        // Get only assignable classes of our collection
        final CoreObject<X> filtered = cast(c);

        // Provide an invocation handler
        return (X) Objects.getProxy(new InvocationHandler() {
            public Object invoke(Object proxy, final Method method, final Object[] args)
                                                                                        throws Throwable {
                filtered.map(new F1<X, Object>() {
                    public Object f(X x) {

                        try {
                            method.invoke(x, args);
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }

                        return null;
                    }
                });

                return null;
            }
        }, c);
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    @SuppressWarnings("null")
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof CoreObject)) return false;

        final CoreObject<?> other = (CoreObject<?>) obj;

        if (size() != other.size()) return false;

        ListIterator<T> i1 = this.adapter.iterator();
        ListIterator<?> i2 = other.adapter.iterator();

        while (i1.hasNext()) {
            T a = i1.next();
            Object b = i2.next();

            if (a == null && b != null) return false;
            if (a == null && b == null) continue;

            boolean equals = a.equals(b);
            if (!equals) return false;
        }

        return true;
    }

    /**
     * Expands contained arrays into a single array of the given type. This means,
     * if this core wraps a number of cores, collections, lists or arrays, each of
     * which are containing elements on their own, <code>expand()</code> will break
     * up all of these lists and return a single CoreObject wrapping the union of
     * everything that was previously held in them.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", $("b", "c"), new String[]{"d", "e"}).expand(String.class)</code> - Returns a core of size
     * <code>5</code>, directly containing the elements <code>a</code>, <code>b</code>, <code>c</code>, <code>d</code>
     * and <code>e</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param <N> Type of the return core.
     * @param class1 Defines the class element of the returned core's array.
     * @return A CoreObject wrapping all broken up collections, arrays, ...
     */
    @SuppressWarnings("unchecked")
    public <N> CoreObject<N> expand(Class<N> class1) {
        int length = 0;

        if (size() == 0) return new CoreObject<N>(this.commonCore, class1, null);

        // Compute overall size
        for (T x : this) {
            if (x == null) continue;

            // Is it a collection?
            if (x instanceof Collection<?>) {
                length += ((Collection<?>) x).size();
                continue;
            }

            // Is it a core?
            if (x instanceof CoreObject<?>) {
                length += ((CoreObject<?>) x).size();
                continue;
            }

            // An array?
            try {
                length += Array.getLength(x);
                continue;
            } catch (IllegalArgumentException e) {
                //
            }

            // A single object?!
            length++;
        }

        // Generate array
        N[] n = (N[]) Array.newInstance(class1, length);
        int offset = 0;

        // Copy to array
        for (T x : this) {
            if (x == null) continue;

            // Is it a collection?
            if (x instanceof Collection<?>) {
                Object[] array = ((Collection<?>) x).toArray();
                System.arraycopy(array, 0, n, offset, array.length);
                offset += array.length;
                continue;
            }

            // Is it a core?
            if (x instanceof CoreObject<?>) {
                Object[] array = ((CoreObject<?>) x).array(Object.class);
                System.arraycopy(array, 0, n, offset, array.length);
                offset += array.length;
                continue;
            }

            // An array?
            try {
                int size = Array.getLength(x);
                System.arraycopy(x, 0, n, offset, size);
                offset += size;
                continue;
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
            } catch (ArrayStoreException e) {
                //
            } catch (IllegalArgumentException e) {
                //
            }

            // A single element?
            Array.set(n, offset++, x);
        }

        return new CoreObject<N>(this.commonCore, n);
    }

    /**
     * Sends a request to the developers requesting a feature with the given name. The
     * request will be sent to a server and collected. Information of the enclosed objects and the
     * feature request string will be transmitted as well.
     *
     * Examples:
     * <ul>
     * <li><code>$("abba").featurerequest(".palindrome() -- Should be supported!")</code></li>
     * </ul>
     *
     * @param functionName Call this function for example like this
     * $(myobjects).featurerequest(".compress() -- Should compress the given objects.");
     */
    public void featurerequest(String functionName) {
        this.commonCore.manager(ManagerDeveloperFeedback.class).featurerequest(functionName, getClass(), fingerprint(true));
    }

    /**
     * Returns a new core with all null elements set to <code>fillValue</code>, the other
     * elements are transferred unchanged.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", null, "b").fill("x")</code> - Returns a core where the <code>null</code> element is set to
     * <code>"x"</code></li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param fillValue Value used to fill up all <code>null</code> slots.
     *
     * @return A filled up CoreObject.
     */
    public CoreObject<T> fill(T fillValue) {
        if (size() == 0) return this;

        final T[] copy = this.adapter.array();

        for (int i = 0; i < copy.length; i++) {
            copy[i] = copy[i] == null ? fillValue : copy[i];
        }

        return new CoreObject<T>(this.commonCore, copy);
    }

    /**
     * Filters the object using the given function. A compacted array will be returned
     * that contains only values for which f returned true.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "bb", "ccc").filter(f)</code> - Given the filter function returns true for all elements with a
     * length <code>&gt;=2</code> the resulting core contains <code>"bb"</code> and <code>"ccc"</code>.</li>
     * </ul>
     *
     * Multi-threaded.<br/>
     * <br/>
     *
     * @param f If f returns true the object is kept.
     * @param options Supports {@link InvertSelection} if the filter logic should be inverted.
     *
     * @return A new CoreObject of our type, containing only kept elements.
     */
    @SupportsOption(options = { InvertSelection.class })
    public CoreObject<T> filter(final F1Object2Bool<T> f, Option... options) {
        final boolean invert = Options.$(this.commonCore, options).invert();
        final CoreObject<T> rval = map(new F1<T, T>() {
            public T f(T x) {
                final boolean result = f.f(x);

                if ((!invert && result) || (invert == !result)) return x;

                return null;
            }
        });

        return rval.compact();
    }

    /**
     * Filters all object by their toString() value using the given regular
     * expression. Only elements that match the regular expression are being kept.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("ax", "bx", "cy").filter(".y")</code> - Returns a core containing <code>"cy"</code>.</li>
     * </ul>
     *
     * Multi-threaded.<br/>
     * <br/>
     *
     * @param regex The regular expression to use.
     * @param options Supports INVERT_SELECTION if the filter logic should be inverted
     * (options that match the regular expression will not be considered).
     *
     * @return A CoreObject containing a filtered subset of our elements.
     */
    public CoreObject<T> filter(final String regex, Option... options) {
        final Pattern p = Pattern.compile(regex);

        return filter(new F1Object2Bool<T>() {
            public boolean f(T x) {
                final Matcher matcher = p.matcher(x.toString());
                return matcher.matches();
            }
        }, options);
    }

    /**
     * Finds the first element that is not null.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$(null, "a", "b").first()</code> - Returns <code>"a"</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return The first element that was not null, or null, if all elements
     * were null.
     */
    public T first() {
        for (T t : this) {
            if (t != null) return t;
        }
        return null;
    }

    /**
     * Generates a textual fingerprint for this element for debugging purporses.
     *
     * @param detailed If the fingerprint should contain detailed information or not.
     * @return A user-readable string which can be printed.
     */
    protected String fingerprint(boolean detailed) {
        final StringBuilder sb = new StringBuilder();
        sb.append("@(");
        sb.append(getClass().getSimpleName());
        sb.append("; outerSize:");
        sb.append(size());
        sb.append("; innerSize:");

        // Append inner size
        Object first = null;
        int ctr = 0;

        // Count elements and extract first nonnull element.
        for (T next : this) {
            if (next != null) {
                ctr++;
                if (first == null) first = next;
            }
        }

        sb.append(ctr);

        // Append type of first element (disabled)
        if (first != null && detailed) {
            sb.append("; firstElement:");
            sb.append(first.getClass().getSimpleName());
        }

        // Append fingerprint
        if (size() <= 16) {
            sb.append("; fingerprint:");

            for (T next : this) {
                if (next != null) {
                    sb.append(next.getClass().getSimpleName().charAt(0));
                } else
                    sb.append(".");
            }
        }

        sb.append(")");
        return sb.toString();
    }

    /**
     * Folds the given object, multi-threaded version. Fold removes two arbitrary elements,
     * executes <code>f()</code> on them and stores the result again. This is done in parallel until
     * only one element remains.<br/>
     * <br/>
     *
     * It is guaranteed that each element will have been compared at least once, but the chronological-
     * or parameter-order when and where this occurs is, in contrast to <code>reduce()</code>, not defined.
     * <code>Null</code> elements are gracefully ignored.<br/>
     * <br/>
     *
     * At present, <code>reduce()</code> is much faster for simple operations and small cores, as it involves much less
     * synchronization overhead, while <code>fold()</code> has advantages especially
     * with very complex <code>f</code> operators.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$(1, 2, 3, 4).fold(fmax)</code> - When <code>fmax</code> returns the larger of both objects the
     * resulting core will contain <code>4</code>.</li>
     * </ul>
     *
     * Multi-threaded. Heavyweight.<br/>
     * <br/>
     *
     * @param f The reduce function. Takes two elements, returns one.
     * @param options Supports {@link MapType}.
     * @return A CoreObject, containing at most a single element.
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @SupportsOption(options = { MapType.class })
    public CoreObject<T> fold(final F2ReduceObjects<T> f, Option... options) {

        // In case we only have zero or one elements, don't do anything
        if (size() <= 1) return this;

        final AtomicReferenceArray array = new AtomicReferenceArray(this.adapter.array());
        final Folder<T> folder = new Folder<T>(this) {
            @Override
            public void handle(int i, int j, int destination) {
                // Get the in-value from the source-array

                final T ii = (T) array.get(i);
                final T jj = (T) array.get(j);

                if (ii == null && jj == null) return;
                if (ii == null && jj != null) {
                    array.set(destination, jj);
                    return;
                }

                if (ii != null && jj == null) {
                    array.set(destination, ii);
                    return;
                }

                array.set(destination, f.f(ii, jj));
            }
        };

        // Now do fold ...
        fold(folder, options);

        T[] target = (T[]) Array.newInstance(this.adapter.clazz(), 1); // Arrays.copyOf(this.t, 1);
        target[0] = (T) array.get(0);

        // ... and return result.
        return new CoreObject<T>(this.commonCore, target);
    }

    /**
     * Performs the given operation on each element and returns a new core. This is the
     * single-threaded version of map().<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", null, "c").forEach(f)</code> - Performs the operation <code>f</code> on each element of the
     * core, except <code>null</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param <R> Return type.
     * @param f Mapper function.
     * @param _options Relevant options: <code>OptionMapType</code>.
     *
     * @return A CoreObject containing the mapped elements in a stable order.
     */
    @SuppressWarnings("unchecked")
    public <R> CoreObject<R> forEach(final F1<T, R> f, Option... _options) {

        // Create a mapper and iterate over it
        final Mapper<T, R> mapper = mapper(f, _options);
        for (int i = 0; i < size(); i++) {
            mapper.handle(i);
        }

        // ... and return result.
        return new CoreObject<R>(this.commonCore, mapper.getFinalReturnArray());
    }

    /**
     * Performs the given operation for each <code>n</code> elements of this core.
     * Elements will only be used once, so for example <code>forEach(f, 2)</code> means
     * that <code>f</code> will be called with elements <code>f(0, 1)</code>, <code>f(2, 3)</code> ... Remaining
     * elements are ignored. This function also acts on <code>null</code> elements. If you don't want that,
     * <code>compact()</code> the core.
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", null, "c").forEach(f)</code> - Performs the operation <code>f</code> on each element of the
     * core, except <code>null</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param <R> The return type.
     * @param f The function to execute for each <code>n</code> elements.
     * @param n The number of elements to put into <code>f</code>
     * @return A core with the new elements.
     */
    @SuppressWarnings("unchecked")
    public <R> CoreObject<R> forEach(final Fn<T, R> f, int n) {
        if (size() == 0) return new CoreObject<R>(this.commonCore, null, null);

        R[] rval = null;
        T[] slice = (T[]) Array.newInstance(this.adapter.clazz(), n); // Arrays.copyOf(this.t, n);

        int ptr = 0;
        int tptr = 0;

        // Now go over the array
        for (int i = 0; i < size(); i++) {
            T e = this.adapter.get(i);

            // When our current element is null, do nothing.
            if (e == null) continue;

            // Store element to slice
            slice[ptr++] = e;

            // If the slice is not full, continue
            if (ptr < n) continue;

            // Execute the call
            R result = f.f(slice);

            // If we have a result, create result array
            if (rval == null && result != null) {
                rval = (R[]) Array.newInstance(result.getClass(), size() / n);
            }

            // If we have the arry, store the result
            if (rval != null) {
                rval[tptr] = result;
            }

            // Increase the target ptr in any case and reset the source ptr
            tptr++;
            ptr = 0;
        }

        // ... and return result.
        return new CoreObject<R>(this.commonCore, rval);
    }

    /**
     * Return the element at the the given relative position (0 <= x <= 1) or return <code>dflt</code> if that element
     * is null.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$("a", null, "c").get(0.5, "b")</code> - Returns <code>"b"</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param percent 0.0 returns the first element, 1.0 the last element, 0.5 returns the
     * element in the
     * middle, and so on.
     * @param dflt The value to return if null had been returned otherwise.
     *
     * @return The value at the requested position, or dflt if there is none.
     */
    public T get(double percent, T dflt) {
        if (Double.isNaN(percent)) return dflt;
        if (percent < 0) return dflt;
        if (percent > 1) return dflt;

        if (size() == 0) return dflt;

        int offset = (int) (percent * size());
        if (offset >= size()) return dflt;

        return this.adapter.get(offset);
    }

    /**
     * Return an element at the the relative position (0 <= x <= 1).<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c", "d", "e").get(0.75)</code> - Returns <code>"d"</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param percent 0.0 returns the first element, 1.0 the last element, 0.5 returns the
     * element in the
     * middle, and so on.
     *
     * @return The value at the requested position, or null if there is none.
     */
    public T get(double percent) {
        return get(percent, null);
    }

    /**
     * Returns the first element that is an instance of the requested type.
     *
     * Examples:
     * <ul>
     * <li><code>$(1, new Object(), "Hi").get(String.class, "Oops")</code> - Returns <code>"Hi"</code>.</li>
     * </ul>
     *
     *
     * Single-threaded. Heavyweight.<br/>
     * <br/>
     *
     * @param <X> Subtype to request.
     * @param request A subclass of our type to request.
     * @param dflt The value to return when no class was found.
     *
     * @return The first object that is assignable to request, or dflt if there was no
     * such element.
     */
    @SuppressWarnings("unchecked")
    public <X extends T> X get(Class<X> request, X dflt) {
        final ListIterator<T> iterator = this.adapter.iterator();
        while (iterator.hasNext()) {
            final T next = iterator.next();
            if (next != null && request.isAssignableFrom(next.getClass()))
                return (X) next;

        }

        return dflt;
    }

    /**
     * Return the ith element.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").get(-1)</code> - Returns <code>"c"</code>.</li>
     * </ul>
     *
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param i Position to retrieve. Negative indices are treated as values starting at
     * the end (i.e., -1 is the last element, -2 the second-last, ...)
     *
     * @return The element at the given position.
     */
    public T get(int i) {
        final int offset = indexToOffset(i);

        if (offset < 0 || offset > size()) return null;

        return this.adapter.get(offset);
    }

    /**
     * Return the ith element or dflt if the element if otherwise <code>null</code> had
     * been returned.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", null).get(2, "c")</code> - Returns <code>"c"</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param i Position to retrieve. Negative indices are treated as values starting at
     * the end (i.e., -1 is the last element, -2 the second-last, ...)
     * @param dflt The value to return if null had been returned.
     *
     * @return Unless dflt is null, this function is guaranteed to return a non-null
     * value.
     */
    public T get(int i, T dflt) {
        final T rval = get(i);
        return rval == null ? dflt : rval;
    }

    /**
     * Returns the first element, or, if there is none, return dflt.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(name).get("Unknown")</code> - Returns <code>"Unknown"</code> if <code>name</code> is
     * <code>null</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param dflt The value to return if get(0) is null.
     * @return Unless dflt is null, this function is guaranteed to return a non-null
     * value.
     */
    public T get(T dflt) {
        return get(0, dflt);
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return this.adapter.hashCode();
    }

    /**
     * Checks if all elements are not null. If the core is empty, <code>false</code> is returned as well.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", null, "b").hasAll()</code> - Returns <code>false</code>.</li>
     * <li><code>$("x").hasAll()</code> - Returns <code>true</code>.</li>
     * <li><code>$().hasAll()</code> - Returns <code>false</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return True if all elements are not null, false if a single element was null.
     */
    public boolean hasAll() {
        if (size() == 0) return false;

        for (T t : this) {
            if (t == null) return false;
        }

        return true;
    }

    /**
     * Checks if the element has any element. If the core is empty, <code>false</code> is returned.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(null, "b").hasAny()</code> - Returns <code>true</code>.</li>
     * <li><code>$().hasAny()</code> - Returns <code>false</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return True if any element is set. False if all elements are null.
     */
    public boolean hasAny() {
        for (T t : this) {
            if (t != null) return true;
        }

        return false;
    }

    /**
     * If all elements are present, execute f0.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(null, "b").ifAll(f)</code> - Does not execute f.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param f0 The function to execute if all elements are given.
     * @return This core.
     */
    public CoreObject<T> ifAll(F0 f0) {
        if (hasAll()) f0.f();
        return this;
    }

    /**
     * Returns the first index positions for all objects equal to the given object, or null if no object
     * equalled the given one.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "c", "b").index("c", "b", "a")</code> - Returns a core <code>$(1, 2, 0)</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param objects The objects to return the first index for.
     * @return A {@link CoreNumber} object with the corresponding index position.
     */
    @SuppressWarnings("boxing")
    public CoreNumber index(T... objects) {
        if (objects == null) return new CoreNumber(this.commonCore, new Number[0]);
        Integer indices[] = new Integer[objects.length];

        // Check all objects ...
        for (int i = 0; i < objects.length; i++) {
            final T obj = objects[i];

            final ListIterator<T> iterator = iterator();
            while (iterator.hasNext()) {
                final int j = iterator.nextIndex();
                final T next = iterator.next();

                if (obj != null && obj.equals(next)) {
                    indices[i] = j;
                    break;
                }

                if (obj == null && next == null) {
                    indices[i] = j;
                    break;
                }
            }
        }

        return new CoreNumber(this.commonCore, indices);
    }

    /**
     * Returns a core intersected with another core.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("x", "y", "z").intersect($("y", "z"))</code> - Returns a core <code>$("y", "z")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param other The other core to intersect.
     * @return Returns a core enclosing only objects present in this and the other core.
     */
    public CoreObject<T> intersect(CoreObject<T> other) {
        if (size() == 0) return this;
        if (other.size() == 0) return other;

        final T[] copy = this.adapter.array();

        // Remove every element we in the other core
        for (int i = 0; i < copy.length; i++) {
            final T element = copy[i];
            if (element == null) continue;

            boolean found = false;

            // Check if the copy contains the element
            for (T x : other) {
                if (x == null || !x.equals(element)) continue;
                found = true;
                break;
            }

            // If not in both, remove.
            if (!found) {
                copy[i] = null;
            }
        }

        // Return a compacted core.
        return new CoreObject<T>(this.commonCore, copy).compact();
    }

    /**
     * Returns a core intersected with another array.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$("x", "y", "z").intersect("a", "x", "b")</code> - Returns a core <code>$("x")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param other The array to intersect.
     * @return Returns a core enclosing only objects present in this core and the other array.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public CoreObject<T> intersect(T... other) {
        return intersect(new CoreObject(this.commonCore, other));
    }

    /**
     * Returns the wrapped collection as a list.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(array).list()</code> - Returns a typed {@link List} for the given array.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return A list containing all elements. Null values should be preserved.
     */
    public List<T> list() {
        return new ArrayList<T>(this.adapter.unsafelist());
    }

    /**
     * Maps the core's content with the given function and returns the result. This is the
     * most fundamental function of jCores. If the core is of size 0 nothing is done, if it is of size 1 <code>f</code>
     * is executed directly. In all other cases <code>map</code> (at least in the
     * current implementation) will go parallel <i>on demand</i>. It takes a test run for the
     * first element and measures the time to process it. If the estimated time it takes to
     * complete the rest of the core is less than the measured time it takes to go parallel (which
     * has some overhead), no parallelization is being performed.<br/>
     * <br/>
     *
     * As a general rule of thumb, <code>map</code> works relatively best on large cores (number of elements) and
     * time-consuming <code>f</code>-
     * operations and it works worst on small cores and very simple <code>f</code>. However,
     * the good message is that these disadvantageous cores/functions only impact your
     * application's performance in case you call <code>map</code> on them hundreds of
     * thousands times a second, as the absolute overhead is still very small.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$.range(1000).map(convert)</code> - Given <code>convert</code> performs some conversion, this would
     * convert the numbers from 0 to 999 in parallel (using as many CPUs as there are available).</li>
     * </ul>
     *
     * Multi-threaded.<br/>
     * <br/>
     *
     * <b>Warning:</b> The larger the core (number of objects) the more you should make sure
     * that <code>f</code> is as <i>isolated</i> as possible, since sharing even a single object
     * (e.g., a shared {@link Random} object like <code>$.random()</code>) among different mapper
     * threads can have a dramatic performance impact. In some cases (e.g., many CPUs (>2), large
     * core (<code>size >> 1000</code>), simple <code>f</code> with shared, synchronized variable
     * access) the performance of <code>map</code> can even drop below the performance of <code>forEach</code>.<br/>
     * <br/>
     *
     *
     * @param <R> Return type.
     * @param f Mapper function, must be thread-safe.
     * @param _options Relevant options: {@link MapType}.
     *
     * @return A CoreObject containing the mapped elements in a stable order.
     */
    @SuppressWarnings("unchecked")
    @SupportsOption(options = { MapType.class })
    public <R> CoreObject<R> map(final F1<T, R> f, Option... _options) {

        // Map what we got
        final Mapper<T, R> mapper = mapper(f, _options);
        map(mapper, _options);

        // ... and return result.
        return new CoreObject<R>(this.commonCore, mapper.getFinalReturnArray());
    }

    /**
     * Prints all strings to the console. Almost the same as <code>string().print()</code>,
     * except that this method returns a CoreObject again.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").print().intersect("a").print()</code> - The first output will be <code>a b c</code>,
     * then again <code>a</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return Returns this CoreObject object again.
     */
    public CoreObject<T> print() {
        if (size() == 0) return this;

        for (Object s : this) {
            if (s == null) continue;
            System.out.println(s);
        }

        return this;
    }

    /**
     * Prints all strings to the console in a single line with the given joiner. <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").print(",")</code> - Prints <code>a,b,c</code></li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @since 1.0
     * @param joiner The string to put in between the elements.
     * @return Returns this CoreObject object again.
     */
    public CoreObject<T> print(String joiner) {
        System.out.println(string().join(joiner));
        return this;
    }

    /**
     * Returns a randomly selected object, including null values.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").random()</code> - Returns ... well, we don't know yet.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return A randomly selected object from this core.
     */
    public T random() {
        final int size = size();
        if (size == 0) return null;
        return this.adapter.get(this.commonCore.random().nextInt(size));
    }

    /**
     * Returns a randomly selected subset, including null values. The elements will be
     * returned in a random order. Elements will never be drawn twice.<br/>
     * <br/>
     *
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c", "d").random(0.5)</code> - Could return <code>$("c", "a")</code>, but never
     * <code>$("b", "b")</code>.</li>
     * </ul>
     *
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param percent Specifies how many percent of elements of this core should be in the
     * resulting core. For example <code>0.5</code> means that half of the elements of
     * this core will be randomly selected and returned, <code>0.0</code> means an empty
     * core will be returned and <code>1.0</code> a shuffled core will be returned.
     *
     * @return A core enclosing randomly selected objects.
     */
    public CoreObject<T> random(double percent) {
        final double p = Math.max(Math.min(1.0, percent), 0.0);
        return random((int) (p * size()));
    }

    /**
     * Returns a randomly selected subset, including null values. The elements will be
     * returned in a random order.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c", "d").random(2)</code> - Same as <code>.random(0.5)</code> in the example above.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param newSize Specifies how many elements of this core should be in the
     * resulting core.
     *
     * @return A core enclosing randomly selected objects.
     */
    public CoreObject<T> random(int newSize) {
        final int size = size();

        if (size == 0) return this;

        // Create a shuffletable
        final T[] copyOf = this.adapter.array();

        // Shuffle the copy
        for (int i = copyOf.length - 1; i >= 1; i--) {
            int j = this.commonCore.random().nextInt(i + 1);

            T x = copyOf[j];
            copyOf[j] = copyOf[i];
            copyOf[i] = x;
        }

        // And return the first newSize elements
        return new CoreObject<T>(this.commonCore, Arrays.copyOfRange(copyOf, 0, newSize));
    }

    /**
     * Reduces the given object, single-threaded version. Reduce takes the two leftmost elements,
     * executes <code>f()</code> on them and stores the result again as the leftmost element. This
     * is done until only one element remains. <code>Null</code> elements are gracefully ignored.<br/>
     * <br/>
     *
     * In contrast to fold() the order in which two element might be reduced is well defined
     * from left to right. You should use <code>reduce()</code> for simple operations and <code>fold()</code> for very
     * complex operations.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", null, "c", "d").reduce(fjoin)</code> - When <code>fjoin</code> joins the left and right
     * String the resulting core will be <code>$("abcd")</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @param f The reduce function. Takes two elements, returns one.
     * @param options Relevant options: {@link MapType}.
     * @return A CoreObject, containing at most a single element.
     */
    @SuppressWarnings("unchecked")
    @SupportsOption(options = { MapType.class })
    public CoreObject<T> reduce(final F2ReduceObjects<T> f, Option... options) {
        T stack = null;

        for (T current : this) {
            // Nothing to do for null elements
            if (current == null) continue;

            // Init stack with first element found
            if (stack == null) {
                stack = current;
                continue;
            }

            stack = f.f(stack, current);
        }

        // We have to use the stack, because we otherwise we might
        // create an array of another type, and not the type f returned.
        final Class<T> type = stack != null ? (Class<T>) stack.getClass() : null;

        return new CoreObject<T>(this.commonCore, type, stack);
    }

    /**
     * Returns a Core with the element order reversed.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").reverse()</code> - Returns a core <code>$("c", "b", "a")</code>.</li>
     * </ul>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return A CoreObject with reversed element order.
     */
    public CoreObject<T> reverse() {
        final int size = size();
        if (size == 0) return this;

        final T[] c = this.adapter.array();
        for (int i = 0; i < size; i++) {
            c[size - i] = this.adapter.get(i);
        }

        return new CoreObject<T>(this.commonCore, c);
    }

    /**
     * Returns how many slots are in this core, counting null elements.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b").size()</code> - Returns 2.</li>
     * <li><code>$("c", null, "d").size()</code> - Returns 3.</li>
     * <li><code>$(null, "e", "f").compact().size()</code> - Returns 2.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @see Core#size()
     * @return .
     */
    @Override
    public int size() {
        return this.adapter.size();
    }

    /**
     * Returns a slice of this core. Element inside this slice start at <code>start</code>.
     * If <code>length</code> is positive it is treated as a length, if it is negative, it
     * is treated as a (inclusive) end-index.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c", "d").slice(0, 2)</code> - Returns <code>$("a", "b")</code>.</li>
     * <li><code>$("a", "b", "c", "d").slice(1, -1)</code> - Returns <code>$("b", "c", "d")</code>.</li>
     * <li><code>$("a", "b", "c", "d").slice(-2, 2)</code> - Returns <code>$("c", "d")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param start The start position.
     * @param length If length is positive it is treated as length, if negative as a
     * starting position from the end (-1 equals the last position)
     * @return A ObjectCore wrapping all sliced elements.
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public CoreObject<T> slice(final int start, final int length) {
        if (size() == 0) return this;
        if (length == 0)
            return new CoreObject<T>(this.commonCore, new EmptyAdapter<T>());

        int i = indexToOffset(start);
        int l = length > 0 ? length : indexToOffset(length) - i + 1;

        if (i < 0 || i >= size()) {
            this.commonCore.report(MessageType.MISUSE, "slice() - converted parameter start(" + start + " -> " + i + ") is outside bounds. Returning empty slice.");
            return new CoreObject<T>(this.commonCore, new EmptyAdapter<T>());
        }
        if (l < 0 || i + l > size()) {
            if (l < 0) {
                this.commonCore.report(MessageType.MISUSE, "slice() - converted parameter length(" + length + " -> " + l + ") is outside bounds. Returning empty slice.");
                return new CoreObject<T>(this.commonCore, new EmptyAdapter<T>());
            }

            this.commonCore.report(MessageType.MISUSE, "slice() - converted parameter length(" + length + " -> " + l + ") is outside bounds. Truncating.");
            l -= i + l - size();
        }

        // Check if the result of the slice is actually an adapter, in that case, we use it directly.
        final List<T> slice = this.adapter.slice(i, i + l);
        if (slice instanceof AbstractAdapter) { return new CoreObject<T>(this.commonCore, (AbstractAdapter) slice); }

        // Return a new core with the given result list.
        return new CoreObject<T>(this.commonCore, slice);
    }

    /**
     * Returns a slice of this core. Element inside this slice start at the relative <code>start</code> and end at the
     * relative <code>end</code>. It must hold <code>0.0 <= start <= end <= 1.0</code>.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c", "d").slice(0.0, 0.5)</code> - Returns <code>$("a", "b")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param start The relative start position.
     * @param end The relative end.
     * starting position from the end (-1 equals the last position)
     * @return A ObjectCore wrapping all sliced elements.
     */
    public CoreObject<T> slice(final double start, final double end) {
        if (size() == 0) return this;
        if (start > end) return slice(0, 0);

        final double s = this.commonCore.alg.limit(0, start, 1.0);
        final double e = this.commonCore.alg.limit(0, end, 1.0);

        int size = size();
        int a = (int) (s * size);
        int b = (int) (e * size);

        return slice(a, b - a);
    }

    /**
     * Returns a new, sorted core using the given {@link Comparator}.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(x, y, z).sort(s)</code> - Returns a sorted core with an order specified by <code>s</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param c Comparator to use. Caution, <code>c</code> will be called with <code>null</code> values
     * for non-existing elements, <code>compact()</code> the core before if you don't want
     * this behavior.
     * @return A CoreObject with sorted entries.
     */
    public CoreObject<T> sort(Comparator<T> c) {
        if (size() == 0) return this;

        final T[] copyOf = this.adapter.array();
        Arrays.sort(copyOf, c);

        return new CoreObject<T>(this.commonCore, copyOf);
    }

    /**
     * Returns a new, sorted core. If the elements of this core are not sortable
     * (i.e, implementing {@link Comparable}), simply this core will be returned
     * again.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("c", "a", "b").sort()</code> - Returns <code>$("a", "b", "c")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return A CoreObject with sorted entries.
     */
    public CoreObject<T> sort() {
        if (size() == 0) return this;

        // TODO: Can't we be faster if we do the sort on our own?
        final T[] copyOf = this.adapter.array();

        try {
            Arrays.sort(copyOf);
        } catch (ClassCastException e) {
            this.commonCore.report(MessageType.EXCEPTION, "Unable to sort core, elements not comparable: " + fingerprint(true));
            return this;
        } catch (NullPointerException e) {
            this.commonCore.report(MessageType.PERFORMANCE, "Make sure cores are compact() before sorting them: " + fingerprint(true));
            return compact().sort();
        }

        return new CoreObject<T>(this.commonCore, copyOf);
    }

    /**
     * Converts all elements to strings by calling <code>.toString()</code> on each
     * element.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$(1, 2).string()</code> - Returns <code>$("1", "2")</code>.</li>
     * </ul>
     *
     * Multi-threaded. <br/>
     * <br/>
     *
     * @return A CoreString containing all <code>toString()</code> output.
     */
    public CoreString string() {
        return map(new F1<T, String>() {
            public String f(T x) {
                return x.toString();
            }
        }).as(CoreString.class);
    }

    /**
     * Returns a core containing all elements of this core that are not
     * in the passed core.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "b", "c").subtract($("b"))</code> - Returns <code>$("a", "c")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param toSubtract The core to subtract from this core.
     *
     * @return A CoreObject containing all objects of this core that are not
     * in the other core.
     */
    public CoreObject<T> subtract(CoreObject<T> toSubtract) {
        if (size() == 0 || toSubtract.size() == 0) return this;

        final T[] copy = this.adapter.array();

        // Remove every element we in the other core
        for (int i = 0; i < toSubtract.size(); i++) {
            final T element = toSubtract.get(i);
            if (element == null) continue;

            // Check if the copy contains the element
            for (int j = 0; j < copy.length; j++) {
                final T our = copy[j];
                if (our == null || !our.equals(element)) continue;
                copy[j] = null;
            }
        }

        return new CoreObject<T>(this.commonCore, copy);
    }

    /**
     * Returns a core containing all elements of this core and that are not
     * in the passed array.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "c").subtract("a", "c")</code> - Returns an empty core <code>$()</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @param toSubtract The array to subtract from this core.
     *
     * @return A CoreObject containing all objects of this core that are not
     * in the other array.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public CoreObject<T> subtract(T... toSubtract) {
        return subtract(new CoreObject(this.commonCore, toSubtract));
    }

    /**
     * Returns a core containing only unique objects, i.e., object
     * mutually un- <code>equal()</code>.<br/>
     * <br/>
     *
     * Examples:
     * <ul>
     * <li><code>$("a", "c", "a", "b").unique()</code> - Returns <code>$("a", "c", "b")</code>.</li>
     * </ul>
     *
     * Single-threaded. <br/>
     * <br/>
     *
     * @return A CoreObject containing only unique, non-null objects.
     */
    public CoreObject<T> unique() {
        if (size() == 0) return this;

        final T[] copy = this.adapter.array();

        // Now check for each element
        for (int i = 1; i < copy.length; i++) {
            // If it is null, no nothing
            if (copy[i] == null) continue;

            // Check each previous element
            for (int j = 0; j < i; j++) {
                // If the current element is equal to a previous element,
                // this element can be nulled
                if (copy[i].equals(copy[j])) {
                    copy[i] = null;
                    break;
                }
            }
        }

        // Return the new, unique core.
        return new CoreObject<T>(this.commonCore, copy).compact();
    }

    /**
     * Returns the core's array, extremely fast when the original objects wrapped in this core were an array.
     * Use of this method is strongly discouraged and usually only needed in a few very special cases. Do not
     * change the array! <br/>
     * <br/>
     *
     * Also, even though the method is parameterized, in some cases it does not return
     * the type of array it indicates due to some black jCores magic (we sometimes haves
     * to 'guess' the type at runtime due to type erasure, which can go wrong when
     * just blindly returning our internal array).<br/>
     * <br/>
     *
     * In most cases <code>array()</code> should be used instead.<br/>
     * <br/>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return A clone of our array.
     */
    public T[] unsafearray() {
        return this.adapter.unsafearray();
    }

    /**
     * Returns an unsafe list for this core, always very fast. Use of this method discouraged but may speed up many
     * operations when used sensibly. The list <b>must not</b> be altered in any way.<br/>
     * <br/>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return A list representation of our core.
     */
    public List<T> unsafelist() {
        return this.adapter.unsafelist();
    }

    /**
     * Returns our internal adapter. The use of this method is strongly discouraged.<br/>
     * . <br/>
     *
     * Single-threaded.<br/>
     * <br/>
     *
     * @return A list representation of our core.
     */
    public AbstractAdapter<T> unsafeadapter() {
        return this.adapter;
    }

    /**
     * Converts an index to an offset.
     *
     * @param index
     * @return An index.
     */
    protected final int indexToOffset(int index) {
        final int size = size();

        if (index >= size) return -1;

        // We also support negative indices.
        if (index < 0) {
            if (-index > size) return -1;
            return size + index;
        }

        return index;
    }

    @SuppressWarnings("rawtypes")
    protected final <R> Mapper mapper(final F1<T, R> f, final Option... options) {
        return new Mapper<T, R>(this, options) {
            @SuppressWarnings("unchecked")
            @Override
            public void handle(int i) {
                // Try to get our return array (could be there if we or someone successfully mapped)
                R[] a = this.returnArray.get();

                // Get the in-value from the source-array
                final T in = CoreObject.this.adapter.get(i);

                // Convert
                if (in == null) return;
                if (this.options.indexer != null) this.options.indexer.i(i);
                final R out = f.f(in);

                // When we had a results and if we haven't had an in-array, create it now, according to the return type
                if (out == null) return;
                if (a == null)
                    a = updateReturnArray((R[]) Array.newInstance(out.getClass(), this.core.size()));

                // Eventually set the out value
                a[i] = out;
            }
        };
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public ListIterator<T> iterator() {
        return this.adapter.iterator();
    }
}
TOP

Related Classes of net.jcores.jre.cores.CoreObject

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.