public boolean contains(final int value) {
            return containsValue(value);
        }

package org.agrona.collections;

import org.agrona.generation.DoNotSub;
import java.io.Serializable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.IntUnaryOperator;
import static org.agrona.BitUtil.findNextPositivePowerOfTwo;
import static org.agrona.collections.CollectionUtil.validateLoadFactor;

/**
 * An open-addressing with linear probing hash map specialised for primitive key and value pairs.
 */
public class Int2IntHashMap implements Map<Integer, Integer>, Serializable {

    @DoNotSub
    static final int MIN_CAPACITY = 8;

    private static final long serialVersionUID = -690554872053575793L;

    private final float loadFactor;

    private final int missingValue;

    @DoNotSub
    private int resizeThreshold;

    @DoNotSub
    private int size = 0;

    private final boolean shouldAvoidAllocation;

    private int[] entries;

    private KeySet keySet;

    private ValueCollection values;

    private EntrySet entrySet;

    /**
     * @param missingValue for the map that represents null.
     */
    public Int2IntHashMap(final int missingValue) {
        this(MIN_CAPACITY, Hashing.DEFAULT_LOAD_FACTOR, missingValue);
    }

    /**
     * @param initialCapacity for the map to override {@link #MIN_CAPACITY}
     * @param loadFactor      for the map to override {@link Hashing#DEFAULT_LOAD_FACTOR}.
     * @param missingValue    for the map that represents null.
     */
    public Int2IntHashMap(@DoNotSub final int initialCapacity, @DoNotSub final float loadFactor, final int missingValue) {
        this(initialCapacity, loadFactor, missingValue, true);
    }

    /**
     * @param initialCapacity       for the map to override {@link #MIN_CAPACITY}
     * @param loadFactor            for the map to override {@link Hashing#DEFAULT_LOAD_FACTOR}.
     * @param missingValue          for the map that represents null.
     * @param shouldAvoidAllocation should allocation be avoided by caching iterators and map entries.
     */
    public Int2IntHashMap(@DoNotSub final int initialCapacity, @DoNotSub final float loadFactor, final int missingValue, final boolean shouldAvoidAllocation) {
        validateLoadFactor(loadFactor);
        this.loadFactor = loadFactor;
        this.missingValue = missingValue;
        this.shouldAvoidAllocation = shouldAvoidAllocation;
        capacity(findNextPositivePowerOfTwo(Math.max(MIN_CAPACITY, initialCapacity)));
    }

    /**
     * The value to be used as a null marker in the map.
     *
     * @return value to be used as a null marker in the map.
     */
    public int missingValue() {
        return missingValue;
    }

    /**
     * Get the load factor applied for resize operations.
     *
     * @return the load factor applied for resize operations.
     */
    public float loadFactor() {
        return loadFactor;
    }

    /**
     * Get the total capacity for the map to which the load factor will be a fraction of.
     *
     * @return the total capacity for the map.
     */
    @DoNotSub
    public int capacity() {
        return entries.length >> 1;
    }

    /**
     * Get the actual threshold which when reached the map will resize.
     * This is a function of the current capacity and load factor.
     *
     * @return the threshold when the map will resize.
     */
    @DoNotSub
    public int resizeThreshold() {
        return resizeThreshold;
    }

    @DoNotSub
    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Get a value using provided key avoiding boxing.
     *
     * @param key lookup key.
     * @return value associated with the key or {@link #missingValue()} if key is not found in the map.
     */
    public int get(final int key) {
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int index = Hashing.evenHash(key, mask);
        int value = missingValue;
        while (entries[index + 1] != missingValue) {
            if (entries[index] == key) {
                value = entries[index + 1];
                break;
            }
            index = next(index, mask);
        }
        return value;
    }

    /**
     * Put a key value pair in the map.
     *
     * @param key   lookup key
     * @param value new value, must not be {@link #missingValue()}
     * @return previous value associated with the key, or {@link #missingValue()} if none found
     * @throws IllegalArgumentException if value is {@link #missingValue()}
     */
    public int put(final int key, final int value) {
        if (value == missingValue) {
            throw new IllegalArgumentException("cannot accept missingValue");
        }
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int index = Hashing.evenHash(key, mask);
        int oldValue = missingValue;
        while (entries[index + 1] != missingValue) {
            if (entries[index] == key) {
                oldValue = entries[index + 1];
                break;
            }
            index = next(index, mask);
        }
        if (oldValue == missingValue) {
            ++size;
            entries[index] = key;
        }
        entries[index + 1] = value;
        increaseCapacity();
        return oldValue;
    }

    private void increaseCapacity() {
        if (size > resizeThreshold) {
            @DoNotSub
            final int newCapacity = entries.length;
            rehash(newCapacity);
        }
    }

    private void rehash(@DoNotSub final int newCapacity) {
        final int[] oldEntries = entries;
        @DoNotSub
        final int length = entries.length;
        capacity(newCapacity);
        final int[] newEntries = entries;
        @DoNotSub
        final int mask = entries.length - 1;
        for (@DoNotSub int keyIndex = 0; keyIndex < length; keyIndex += 2) {
            final int value = oldEntries[keyIndex + 1];
            if (value != missingValue) {
                final int key = oldEntries[keyIndex];
                @DoNotSub
                int index = Hashing.evenHash(key, mask);
                while (newEntries[index + 1] != missingValue) {
                    index = next(index, mask);
                }
                newEntries[index] = key;
                newEntries[index + 1] = value;
            }
        }
    }

    /**
     * Primitive specialised forEach implementation.
     * <p>
     * NB: Renamed from forEach to avoid overloading on parameter types of lambda
     * expression, which doesn't play well with type inference in lambda expressions.
     *
     * @param consumer a callback called for each key/value pair in the map.
     */
    public void intForEach(final IntIntConsumer consumer) {
        @DoNotSub
        final int length = entries.length;
        @DoNotSub
        int remaining = size;
        for (@DoNotSub int valueIndex = 1; remaining > 0 && valueIndex < length; valueIndex += 2) {
            if (entries[valueIndex] != missingValue) {
                consumer.accept(entries[valueIndex - 1], entries[valueIndex]);
                --remaining;
            }
        }
    }

    /**
     * Int primitive specialised containsKey.
     *
     * @param key the key to check.
     * @return true if the map contains key as a key, false otherwise.
     */
    public boolean containsKey(final int key) {
        return get(key) != missingValue;
    }

    /**
     * Does the map contain the value.
     *
     * @param value to be tested against contained values.
     * @return true if contained otherwise value.
     */
    public boolean containsValue(final int value) {
        boolean found = false;
        if (value != missingValue) {
            @DoNotSub
            final int length = entries.length;
            @DoNotSub
            int remaining = size;
            for (@DoNotSub int valueIndex = 1; remaining > 0 && valueIndex < length; valueIndex += 2) {
                if (missingValue != entries[valueIndex]) {
                    if (value == entries[valueIndex]) {
                        found = true;
                        break;
                    }
                    --remaining;
                }
            }
        }
        return found;
    }

    public void clear() {
        if (size > 0) {
            Arrays.fill(entries, missingValue);
            size = 0;
        }
    }

    /**
     * Compact the backing arrays by rehashing with a capacity just larger than current size
     * and giving consideration to the load factor.
     */
    public void compact() {
        @DoNotSub
        final int idealCapacity = (int) Math.round(size() * (1.0d / loadFactor));
        rehash(findNextPositivePowerOfTwo(Math.max(MIN_CAPACITY, idealCapacity)));
    }

    /**
     * Primitive specialised version of {@link #computeIfAbsent(Object, Function)}
     *
     * @param key             to search on.
     * @param mappingFunction to provide a value if the get returns null.
     * @return the value if found otherwise the missing value.
     */
    public int computeIfAbsent(final int key, final IntUnaryOperator mappingFunction) {
        int value = get(key);
        if (value == missingValue) {
            value = mappingFunction.applyAsInt(key);
            if (value != missingValue) {
                put(key, value);
            }
        }
        return value;
    }

    // ---------------- Boxed Versions Below ----------------
    public Integer get(final Object key) {
        return valOrNull(get((int) key));
    }

    public Integer put(final Integer key, final Integer value) {
        return valOrNull(put((int) key, (int) value));
    }

    public void forEach(final BiConsumer<? super Integer, ? super Integer> action) {
        intForEach(action::accept);
    }

    public boolean containsKey(final Object key) {
        return containsKey((int) key);
    }

    public boolean containsValue(final Object value) {
        return containsValue((int) value);
    }

    public void putAll(final Map<? extends Integer, ? extends Integer> map) {
        for (final Map.Entry<? extends Integer, ? extends Integer> entry : map.entrySet()) {
            put(entry.getKey(), entry.getValue());
        }
    }

    public KeySet keySet() {
        if (null == keySet) {
            keySet = new KeySet();
        }
        return keySet;
    }

    public ValueCollection values() {
        if (null == values) {
            values = new ValueCollection();
        }
        return values;
    }

    public EntrySet entrySet() {
        if (null == entrySet) {
            entrySet = new EntrySet();
        }
        return entrySet;
    }

    public Integer remove(final Object key) {
        return valOrNull(remove((int) key));
    }

    /**
     * Remove value from the map using given key avoiding boxing.
     *
     * @param key whose mapping is to be removed from the map.
     * @return removed value or {@link #missingValue()} if key was not found in the map.
     */
    public int remove(final int key) {
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int keyIndex = Hashing.evenHash(key, mask);
        int oldValue = missingValue;
        while (entries[keyIndex + 1] != missingValue) {
            if (entries[keyIndex] == key) {
                oldValue = entries[keyIndex + 1];
                entries[keyIndex + 1] = missingValue;
                size--;
                compactChain(keyIndex);
                break;
            }
            keyIndex = next(keyIndex, mask);
        }
        return oldValue;
    }

    @SuppressWarnings("FinalParameters")
    private void compactChain(@DoNotSub int deleteKeyIndex) {
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int keyIndex = deleteKeyIndex;
        while (true) {
            keyIndex = next(keyIndex, mask);
            if (entries[keyIndex + 1] == missingValue) {
                break;
            }
            @DoNotSub
            final int hash = Hashing.evenHash(entries[keyIndex], mask);
            if ((keyIndex < hash && (hash <= deleteKeyIndex || deleteKeyIndex <= keyIndex)) || (hash <= deleteKeyIndex && deleteKeyIndex <= keyIndex)) {
                entries[deleteKeyIndex] = entries[keyIndex];
                entries[deleteKeyIndex + 1] = entries[keyIndex + 1];
                entries[keyIndex + 1] = missingValue;
                deleteKeyIndex = keyIndex;
            }
        }
    }

    /**
     * Get the minimum value stored in the map. If the map is empty then it will return {@link #missingValue()}
     *
     * @return the minimum value stored in the map.
     */
    public int minValue() {
        final int missingValue = this.missingValue;
        int min = size == 0 ? missingValue : Integer.MAX_VALUE;
        @DoNotSub
        final int length = entries.length;
        for (@DoNotSub int valueIndex = 1; valueIndex < length; valueIndex += 2) {
            final int value = entries[valueIndex];
            if (value != missingValue) {
                min = Math.min(min, value);
            }
        }
        return min;
    }

    /**
     * Get the maximum value stored in the map. If the map is empty then it will return {@link #missingValue()}
     *
     * @return the maximum value stored in the map.
     */
    public int maxValue() {
        final int missingValue = this.missingValue;
        int max = size == 0 ? missingValue : Integer.MIN_VALUE;
        @DoNotSub
        final int length = entries.length;
        for (@DoNotSub int valueIndex = 1; valueIndex < length; valueIndex += 2) {
            final int value = entries[valueIndex];
            if (value != missingValue) {
                max = Math.max(max, value);
            }
        }
        return max;
    }

    public String toString() {
        if (isEmpty()) {
            return "{}";
        }
        final EntryIterator entryIterator = new EntryIterator();
        entryIterator.reset();
        final StringBuilder sb = new StringBuilder().append('{');
        while (true) {
            entryIterator.next();
            sb.append(entryIterator.getIntKey()).append('=').append(entryIterator.getIntValue());
            if (!entryIterator.hasNext()) {
                return sb.append('}').toString();
            }
            sb.append(',').append(' ');
        }
    }

    /**
     * Primitive specialised version of {@link #replace(Object, Object)}
     *
     * @param key key with which the specified value is associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with the specified key, or
     *         {@link #missingValue()} if there was no mapping for the key.
     */
    public int replace(final int key, final int value) {
        int currentValue = get(key);
        if (currentValue != missingValue) {
            currentValue = put(key, value);
        }
        return currentValue;
    }

    /**
     * Primitive specialised version of {@link #replace(Object, Object, Object)}
     *
     * @param key      key with which the specified value is associated
     * @param oldValue value expected to be associated with the specified key
     * @param newValue value to be associated with the specified key
     * @return {@code true} if the value was replaced
     */
    public boolean replace(final int key, final int oldValue, final int newValue) {
        final int curValue = get(key);
        if (curValue != oldValue || curValue == missingValue) {
            return false;
        }
        put(key, newValue);
        return true;
    }

    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Map)) {
            return false;
        }
        final Map<?, ?> that = (Map<?, ?>) o;
        return size == that.size() && entrySet().equals(that.entrySet());
    }

    @DoNotSub
    public int hashCode() {
        return entrySet().hashCode();
    }

    @DoNotSub
    private static int next(final int index, final int mask) {
        return (index + 2) & mask;
    }

    private void capacity(@DoNotSub final int newCapacity) {
        @DoNotSub
        final int entriesLength = newCapacity * 2;
        if (entriesLength < 0) {
            throw new IllegalStateException("max capacity reached at size=" + size);
        }
        /*@DoNotSub*/
        resizeThreshold = (int) (newCapacity * loadFactor);
        entries = new int[entriesLength];
        Arrays.fill(entries, missingValue);
    }

    private Integer valOrNull(final int value) {
        return value == missingValue ? null : value;
    }

    /**
     * Base iterator implementation.
     */
    abstract class AbstractIterator implements Serializable {

        private static final long serialVersionUID = 5262459454112462433L;

        /**
         * Is current position valid.
         */
        protected boolean isPositionValid = false;

        @DoNotSub
        private int remaining;

        @DoNotSub
        private int positionCounter;

        @DoNotSub
        private int stopCounter;

        final void reset() {
            isPositionValid = false;
            remaining = Int2IntHashMap.this.size;
            final int missingValue = Int2IntHashMap.this.missingValue;
            final int[] entries = Int2IntHashMap.this.entries;
            @DoNotSub
            final int capacity = entries.length;
            @DoNotSub
            int keyIndex = capacity;
            if (entries[capacity - 1] != missingValue) {
                for (@DoNotSub int i = 1; i < capacity; i += 2) {
                    if (entries[i] == missingValue) {
                        keyIndex = i - 1;
                        break;
                    }
                }
            }
            stopCounter = keyIndex;
            positionCounter = keyIndex + capacity;
        }

        /**
         * Returns position of the key of the current entry.
         *
         * @return key position.
         */
        @DoNotSub
        protected final int keyPosition() {
            return positionCounter & entries.length - 1;
        }

        /**
         * Number of remaining elements.
         *
         * @return number of remaining elements.
         */
        @DoNotSub
        public int remaining() {
            return remaining;
        }

        /**
         * Check if there are more elements remaining.
         *
         * @return {@code true} if {@code remaining > 0}.
         */
        public boolean hasNext() {
            return remaining > 0;
        }

        /**
         * Advance to the next entry.
         *
         * @throws NoSuchElementException if no more entries available.
         */
        protected final void findNext() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            final int[] entries = Int2IntHashMap.this.entries;
            final int missingValue = Int2IntHashMap.this.missingValue;
            @DoNotSub
            final int mask = entries.length - 1;
            for (@DoNotSub int keyIndex = positionCounter - 2; keyIndex >= stopCounter; keyIndex -= 2) {
                @DoNotSub
                final int index = keyIndex & mask;
                if (entries[index + 1] != missingValue) {
                    isPositionValid = true;
                    positionCounter = keyIndex;
                    --remaining;
                    return;
                }
            }
            isPositionValid = false;
            throw new IllegalStateException();
        }

        public void remove() {
            if (isPositionValid) {
                @DoNotSub
                final int position = keyPosition();
                entries[position + 1] = missingValue;
                --size;
                compactChain(position);
                isPositionValid = false;
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * Iterator over keys which supports access to unboxed keys via {@link #nextValue()}.
     */
    public final class KeyIterator extends AbstractIterator implements Iterator<Integer>, Serializable {

        private static final long serialVersionUID = 9151493609653852972L;

        public Integer next() {
            return nextValue();
        }

        /**
         * Return next key.
         *
         * @return next key.
         */
        public int nextValue() {
            findNext();
            return entries[keyPosition()];
        }
    }

    /**
     * Iterator over values which supports access to unboxed values.
     */
    public final class ValueIterator extends AbstractIterator implements Iterator<Integer>, Serializable {

        private static final long serialVersionUID = -5670291734793552927L;

        public Integer next() {
            return nextValue();
        }

        /**
         * Return next value.
         *
         * @return next value.
         */
        public int nextValue() {
            findNext();
            return entries[keyPosition() + 1];
        }
    }

    /**
     * Iterator over entries which supports access to unboxed keys and values.
     */
    public final class EntryIterator extends AbstractIterator implements Iterator<Entry<Integer, Integer>>, Entry<Integer, Integer>, Serializable {

        private static final long serialVersionUID = 1744408438593481051L;

        public Integer getKey() {
            return getIntKey();
        }

        /**
         * Returns the key of the current entry.
         *
         * @return the key.
         */
        public int getIntKey() {
            return entries[keyPosition()];
        }

        public Integer getValue() {
            return getIntValue();
        }

        /**
         * Returns the value of the current entry.
         *
         * @return the value.
         */
        public int getIntValue() {
            return entries[keyPosition() + 1];
        }

        public Integer setValue(final Integer value) {
            return setValue(value.intValue());
        }

        /**
         * Sets the value of the current entry.
         *
         * @param value to be set.
         * @return previous value of the entry.
         */
        public int setValue(final int value) {
            if (!isPositionValid) {
                throw new IllegalStateException();
            }
            if (missingValue == value) {
                throw new IllegalArgumentException();
            }
            @DoNotSub
            final int keyPosition = keyPosition();
            final int prevValue = entries[keyPosition + 1];
            entries[keyPosition + 1] = value;
            return prevValue;
        }

        public Entry<Integer, Integer> next() {
            findNext();
            if (shouldAvoidAllocation) {
                return this;
            }
            return allocateDuplicateEntry();
        }

        private Entry<Integer, Integer> allocateDuplicateEntry() {
            return new MapEntry(getIntKey(), getIntValue());
        }

        @DoNotSub
        public int hashCode() {
            return Integer.hashCode(getIntKey()) ^ Integer.hashCode(getIntValue());
        }

        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof Entry)) {
                return false;
            }
            final Entry<?, ?> that = (Entry<?, ?>) o;
            return Objects.equals(getKey(), that.getKey()) && Objects.equals(getValue(), that.getValue());
        }

        /**
         * An {@link java.util.Map.Entry} implementation.
         */
        public final class MapEntry implements Entry<Integer, Integer> {

            private final int k;

            private final int v;

            /**
             * Constructs entry with given key and value.
             *
             * @param k key.
             * @param v value.
             */
            public MapEntry(final int k, final int v) {
                this.k = k;
                this.v = v;
            }

            public Integer getKey() {
                return k;
            }

            public Integer getValue() {
                return v;
            }

            public Integer setValue(final Integer value) {
                return Int2IntHashMap.this.put(k, value.intValue());
            }

            @DoNotSub
            public int hashCode() {
                return Integer.hashCode(getIntKey()) ^ Integer.hashCode(getIntValue());
            }

            @DoNotSub
            public boolean equals(final Object o) {
                if (!(o instanceof Map.Entry)) {
                    return false;
                }
                final Entry<?, ?> e = (Entry<?, ?>) o;
                return (e.getKey() != null && e.getValue() != null) && (e.getKey().equals(k) && e.getValue().equals(v));
            }

            public String toString() {
                return k + "=" + v;
            }
        }
    }

    /**
     * Set of keys which supports optional cached iterators to avoid allocation.
     */
    public final class KeySet extends AbstractSet<Integer> implements Serializable {

        private static final long serialVersionUID = -7645453993079742625L;

        private final KeyIterator keyIterator = shouldAvoidAllocation ? new KeyIterator() : null;

        public KeyIterator iterator() {
            KeyIterator keyIterator = this.keyIterator;
            if (null == keyIterator) {
                keyIterator = new KeyIterator();
            }
            keyIterator.reset();
            return keyIterator;
        }

        @DoNotSub
        public int size() {
            return Int2IntHashMap.this.size();
        }

        public boolean isEmpty() {
            return Int2IntHashMap.this.isEmpty();
        }

        public void clear() {
            Int2IntHashMap.this.clear();
        }

        public boolean contains(final Object o) {
            return contains((int) o);
        }

        /**
         * Checks if key is contained in the map without boxing.
         *
         * @param key to check.
         * @return {@code true} if key is contained in this map.
         */
        public boolean contains(final int key) {
            return containsKey(key);
        }
    }

    /**
     * Collection of values which supports optionally cached iterators to avoid allocation.
     */
    public final class ValueCollection extends AbstractCollection<Integer> implements Serializable {

        private static final long serialVersionUID = -8925598924781601919L;

        private final ValueIterator valueIterator = shouldAvoidAllocation ? new ValueIterator() : null;

        public ValueIterator iterator() {
            ValueIterator valueIterator = this.valueIterator;
            if (null == valueIterator) {
                valueIterator = new ValueIterator();
            }
            valueIterator.reset();
            return valueIterator;
        }

        @DoNotSub
        public int size() {
            return Int2IntHashMap.this.size();
        }

        public boolean contains(final Object o) {
            return contains((int) o);
        }

        /**
         * Checks if the value is contained in the map.
         *
         * @param value to be checked.
         * @return  {@code true} if value is contained in this map.
         */

    }

    /**
     * Set of entries which supports optionally cached iterators to avoid allocation.
     */
    public final class EntrySet extends AbstractSet<Map.Entry<Integer, Integer>> implements Serializable {

        private static final long serialVersionUID = 63641283589916174L;

        private final EntryIterator entryIterator = shouldAvoidAllocation ? new EntryIterator() : null;

        public EntryIterator iterator() {
            EntryIterator entryIterator = this.entryIterator;
            if (null == entryIterator) {
                entryIterator = new EntryIterator();
            }
            entryIterator.reset();
            return entryIterator;
        }

        @DoNotSub
        public int size() {
            return Int2IntHashMap.this.size();
        }

        public boolean isEmpty() {
            return Int2IntHashMap.this.isEmpty();
        }

        public void clear() {
            Int2IntHashMap.this.clear();
        }

        public boolean contains(final Object o) {
            if (!(o instanceof Entry)) {
                return false;
            }
            final Entry<?, ?> entry = (Entry<?, ?>) o;
            final Integer value = get(entry.getKey());
            return value != null && value.equals(entry.getValue());
        }

        public Object[] toArray() {
            return toArray(new Object[size()]);
        }

        @SuppressWarnings("unchecked")
        public <T> T[] toArray(final T[] a) {
            final T[] array = a.length >= size ? a : (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
            final EntryIterator it = iterator();
            for (@DoNotSub int i = 0; i < array.length; i++) {
                if (it.hasNext()) {
                    it.next();
                    array[i] = (T) it.allocateDuplicateEntry();
                } else {
                    array[i] = null;
                    break;
                }
            }
            return array;
        }
    }
}


while (entries[index + 1] != missingValue) {
            if (entries[index] == key) {
                oldValue = entries[index + 1];
                break;
            }
            index = next(index, mask);
        }

package org.agrona.collections;

import org.agrona.generation.DoNotSub;
import java.io.Serializable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.IntUnaryOperator;
import static org.agrona.BitUtil.findNextPositivePowerOfTwo;
import static org.agrona.collections.CollectionUtil.validateLoadFactor;

/**
 * An open-addressing with linear probing hash map specialised for primitive key and value pairs.
 */
public class Int2IntHashMap implements Map<Integer, Integer>, Serializable {

    @DoNotSub
    static final int MIN_CAPACITY = 8;

    private static final long serialVersionUID = -690554872053575793L;

    private final float loadFactor;

    private final int missingValue;

    @DoNotSub
    private int resizeThreshold;

    @DoNotSub
    private int size = 0;

    private final boolean shouldAvoidAllocation;

    private int[] entries;

    private KeySet keySet;

    private ValueCollection values;

    private EntrySet entrySet;

    /**
     * @param missingValue for the map that represents null.
     */
    public Int2IntHashMap(final int missingValue) {
        this(MIN_CAPACITY, Hashing.DEFAULT_LOAD_FACTOR, missingValue);
    }

    /**
     * @param initialCapacity for the map to override {@link #MIN_CAPACITY}
     * @param loadFactor      for the map to override {@link Hashing#DEFAULT_LOAD_FACTOR}.
     * @param missingValue    for the map that represents null.
     */
    public Int2IntHashMap(@DoNotSub final int initialCapacity, @DoNotSub final float loadFactor, final int missingValue) {
        this(initialCapacity, loadFactor, missingValue, true);
    }

    /**
     * @param initialCapacity       for the map to override {@link #MIN_CAPACITY}
     * @param loadFactor            for the map to override {@link Hashing#DEFAULT_LOAD_FACTOR}.
     * @param missingValue          for the map that represents null.
     * @param shouldAvoidAllocation should allocation be avoided by caching iterators and map entries.
     */
    public Int2IntHashMap(@DoNotSub final int initialCapacity, @DoNotSub final float loadFactor, final int missingValue, final boolean shouldAvoidAllocation) {
        validateLoadFactor(loadFactor);
        this.loadFactor = loadFactor;
        this.missingValue = missingValue;
        this.shouldAvoidAllocation = shouldAvoidAllocation;
        capacity(findNextPositivePowerOfTwo(Math.max(MIN_CAPACITY, initialCapacity)));
    }

    /**
     * The value to be used as a null marker in the map.
     *
     * @return value to be used as a null marker in the map.
     */
    public int missingValue() {
        return missingValue;
    }

    /**
     * Get the load factor applied for resize operations.
     *
     * @return the load factor applied for resize operations.
     */
    public float loadFactor() {
        return loadFactor;
    }

    /**
     * Get the total capacity for the map to which the load factor will be a fraction of.
     *
     * @return the total capacity for the map.
     */
    @DoNotSub
    public int capacity() {
        return entries.length >> 1;
    }

    /**
     * Get the actual threshold which when reached the map will resize.
     * This is a function of the current capacity and load factor.
     *
     * @return the threshold when the map will resize.
     */
    @DoNotSub
    public int resizeThreshold() {
        return resizeThreshold;
    }

    @DoNotSub
    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Get a value using provided key avoiding boxing.
     *
     * @param key lookup key.
     * @return value associated with the key or {@link #missingValue()} if key is not found in the map.
     */
    public int get(final int key) {
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int index = Hashing.evenHash(key, mask);
        int value = missingValue;
        while (entries[index + 1] != missingValue) {
            if (entries[index] == key) {
                value = entries[index + 1];
                break;
            }
            index = next(index, mask);
        }
        return value;
    }

    /**
     * Put a key value pair in the map.
     *
     * @param key   lookup key
     * @param value new value, must not be {@link #missingValue()}
     * @return previous value associated with the key, or {@link #missingValue()} if none found
     * @throws IllegalArgumentException if value is {@link #missingValue()}
     */
    public int put(final int key, final int value) {
        if (value == missingValue) {
            throw new IllegalArgumentException("cannot accept missingValue");
        }
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int index = Hashing.evenHash(key, mask);
        int oldValue = missingValue;

        if (oldValue == missingValue) {
            ++size;
            entries[index] = key;
        }
        entries[index + 1] = value;
        increaseCapacity();
        return oldValue;
    }

    private void increaseCapacity() {
        if (size > resizeThreshold) {
            @DoNotSub
            final int newCapacity = entries.length;
            rehash(newCapacity);
        }
    }

    private void rehash(@DoNotSub final int newCapacity) {
        final int[] oldEntries = entries;
        @DoNotSub
        final int length = entries.length;
        capacity(newCapacity);
        final int[] newEntries = entries;
        @DoNotSub
        final int mask = entries.length - 1;
        for (@DoNotSub int keyIndex = 0; keyIndex < length; keyIndex += 2) {
            final int value = oldEntries[keyIndex + 1];
            if (value != missingValue) {
                final int key = oldEntries[keyIndex];
                @DoNotSub
                int index = Hashing.evenHash(key, mask);
                while (newEntries[index + 1] != missingValue) {
                    index = next(index, mask);
                }
                newEntries[index] = key;
                newEntries[index + 1] = value;
            }
        }
    }

    /**
     * Primitive specialised forEach implementation.
     * <p>
     * NB: Renamed from forEach to avoid overloading on parameter types of lambda
     * expression, which doesn't play well with type inference in lambda expressions.
     *
     * @param consumer a callback called for each key/value pair in the map.
     */
    public void intForEach(final IntIntConsumer consumer) {
        @DoNotSub
        final int length = entries.length;
        @DoNotSub
        int remaining = size;
        for (@DoNotSub int valueIndex = 1; remaining > 0 && valueIndex < length; valueIndex += 2) {
            if (entries[valueIndex] != missingValue) {
                consumer.accept(entries[valueIndex - 1], entries[valueIndex]);
                --remaining;
            }
        }
    }

    /**
     * Int primitive specialised containsKey.
     *
     * @param key the key to check.
     * @return true if the map contains key as a key, false otherwise.
     */
    public boolean containsKey(final int key) {
        return get(key) != missingValue;
    }

    /**
     * Does the map contain the value.
     *
     * @param value to be tested against contained values.
     * @return true if contained otherwise value.
     */
    public boolean containsValue(final int value) {
        boolean found = false;
        if (value != missingValue) {
            @DoNotSub
            final int length = entries.length;
            @DoNotSub
            int remaining = size;
            for (@DoNotSub int valueIndex = 1; remaining > 0 && valueIndex < length; valueIndex += 2) {
                if (missingValue != entries[valueIndex]) {
                    if (value == entries[valueIndex]) {
                        found = true;
                        break;
                    }
                    --remaining;
                }
            }
        }
        return found;
    }

    public void clear() {
        if (size > 0) {
            Arrays.fill(entries, missingValue);
            size = 0;
        }
    }

    /**
     * Compact the backing arrays by rehashing with a capacity just larger than current size
     * and giving consideration to the load factor.
     */
    public void compact() {
        @DoNotSub
        final int idealCapacity = (int) Math.round(size() * (1.0d / loadFactor));
        rehash(findNextPositivePowerOfTwo(Math.max(MIN_CAPACITY, idealCapacity)));
    }

    /**
     * Primitive specialised version of {@link #computeIfAbsent(Object, Function)}
     *
     * @param key             to search on.
     * @param mappingFunction to provide a value if the get returns null.
     * @return the value if found otherwise the missing value.
     */
    public int computeIfAbsent(final int key, final IntUnaryOperator mappingFunction) {
        int value = get(key);
        if (value == missingValue) {
            value = mappingFunction.applyAsInt(key);
            if (value != missingValue) {
                put(key, value);
            }
        }
        return value;
    }

    // ---------------- Boxed Versions Below ----------------
    public Integer get(final Object key) {
        return valOrNull(get((int) key));
    }

    public Integer put(final Integer key, final Integer value) {
        return valOrNull(put((int) key, (int) value));
    }

    public void forEach(final BiConsumer<? super Integer, ? super Integer> action) {
        intForEach(action::accept);
    }

    public boolean containsKey(final Object key) {
        return containsKey((int) key);
    }

    public boolean containsValue(final Object value) {
        return containsValue((int) value);
    }

    public void putAll(final Map<? extends Integer, ? extends Integer> map) {
        for (final Map.Entry<? extends Integer, ? extends Integer> entry : map.entrySet()) {
            put(entry.getKey(), entry.getValue());
        }
    }

    public KeySet keySet() {
        if (null == keySet) {
            keySet = new KeySet();
        }
        return keySet;
    }

    public ValueCollection values() {
        if (null == values) {
            values = new ValueCollection();
        }
        return values;
    }

    public EntrySet entrySet() {
        if (null == entrySet) {
            entrySet = new EntrySet();
        }
        return entrySet;
    }

    public Integer remove(final Object key) {
        return valOrNull(remove((int) key));
    }

    /**
     * Remove value from the map using given key avoiding boxing.
     *
     * @param key whose mapping is to be removed from the map.
     * @return removed value or {@link #missingValue()} if key was not found in the map.
     */
    public int remove(final int key) {
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int keyIndex = Hashing.evenHash(key, mask);
        int oldValue = missingValue;
        while (entries[keyIndex + 1] != missingValue) {
            if (entries[keyIndex] == key) {
                oldValue = entries[keyIndex + 1];
                entries[keyIndex + 1] = missingValue;
                size--;
                compactChain(keyIndex);
                break;
            }
            keyIndex = next(keyIndex, mask);
        }
        return oldValue;
    }

    @SuppressWarnings("FinalParameters")
    private void compactChain(@DoNotSub int deleteKeyIndex) {
        @DoNotSub
        final int mask = entries.length - 1;
        @DoNotSub
        int keyIndex = deleteKeyIndex;
        while (true) {
            keyIndex = next(keyIndex, mask);
            if (entries[keyIndex + 1] == missingValue) {
                break;
            }
            @DoNotSub
            final int hash = Hashing.evenHash(entries[keyIndex], mask);
            if ((keyIndex < hash && (hash <= deleteKeyIndex || deleteKeyIndex <= keyIndex)) || (hash <= deleteKeyIndex && deleteKeyIndex <= keyIndex)) {
                entries[deleteKeyIndex] = entries[keyIndex];
                entries[deleteKeyIndex + 1] = entries[keyIndex + 1];
                entries[keyIndex + 1] = missingValue;
                deleteKeyIndex = keyIndex;
            }
        }
    }

    /**
     * Get the minimum value stored in the map. If the map is empty then it will return {@link #missingValue()}
     *
     * @return the minimum value stored in the map.
     */
    public int minValue() {
        final int missingValue = this.missingValue;
        int min = size == 0 ? missingValue : Integer.MAX_VALUE;
        @DoNotSub
        final int length = entries.length;
        for (@DoNotSub int valueIndex = 1; valueIndex < length; valueIndex += 2) {
            final int value = entries[valueIndex];
            if (value != missingValue) {
                min = Math.min(min, value);
            }
        }
        return min;
    }

    /**
     * Get the maximum value stored in the map. If the map is empty then it will return {@link #missingValue()}
     *
     * @return the maximum value stored in the map.
     */
    public int maxValue() {
        final int missingValue = this.missingValue;
        int max = size == 0 ? missingValue : Integer.MIN_VALUE;
        @DoNotSub
        final int length = entries.length;
        for (@DoNotSub int valueIndex = 1; valueIndex < length; valueIndex += 2) {
            final int value = entries[valueIndex];
            if (value != missingValue) {
                max = Math.max(max, value);
            }
        }
        return max;
    }

    public String toString() {
        if (isEmpty()) {
            return "{}";
        }
        final EntryIterator entryIterator = new EntryIterator();
        entryIterator.reset();
        final StringBuilder sb = new StringBuilder().append('{');
        while (true) {
            entryIterator.next();
            sb.append(entryIterator.getIntKey()).append('=').append(entryIterator.getIntValue());
            if (!entryIterator.hasNext()) {
                return sb.append('}').toString();
            }
            sb.append(',').append(' ');
        }
    }

    /**
     * Primitive specialised version of {@link #replace(Object, Object)}
     *
     * @param key key with which the specified value is associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with the specified key, or
     *         {@link #missingValue()} if there was no mapping for the key.
     */
    public int replace(final int key, final int value) {
        int currentValue = get(key);
        if (currentValue != missingValue) {
            currentValue = put(key, value);
        }
        return currentValue;
    }

    /**
     * Primitive specialised version of {@link #replace(Object, Object, Object)}
     *
     * @param key      key with which the specified value is associated
     * @param oldValue value expected to be associated with the specified key
     * @param newValue value to be associated with the specified key
     * @return {@code true} if the value was replaced
     */
    public boolean replace(final int key, final int oldValue, final int newValue) {
        final int curValue = get(key);
        if (curValue != oldValue || curValue == missingValue) {
            return false;
        }
        put(key, newValue);
        return true;
    }

    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Map)) {
            return false;
        }
        final Map<?, ?> that = (Map<?, ?>) o;
        return size == that.size() && entrySet().equals(that.entrySet());
    }

    @DoNotSub
    public int hashCode() {
        return entrySet().hashCode();
    }

    @DoNotSub
    private static int next(final int index, final int mask) {
        return (index + 2) & mask;
    }

    private void capacity(@DoNotSub final int newCapacity) {
        @DoNotSub
        final int entriesLength = newCapacity * 2;
        if (entriesLength < 0) {
            throw new IllegalStateException("max capacity reached at size=" + size);
        }
        /*@DoNotSub*/
        resizeThreshold = (int) (newCapacity * loadFactor);
        entries = new int[entriesLength];
        Arrays.fill(entries, missingValue);
    }

    private Integer valOrNull(final int value) {
        return value == missingValue ? null : value;
    }

    /**
     * Base iterator implementation.
     */
    abstract class AbstractIterator implements Serializable {

        private static final long serialVersionUID = 5262459454112462433L;

        /**
         * Is current position valid.
         */
        protected boolean isPositionValid = false;

        @DoNotSub
        private int remaining;

        @DoNotSub
        private int positionCounter;

        @DoNotSub
        private int stopCounter;

        final void reset() {
            isPositionValid = false;
            remaining = Int2IntHashMap.this.size;
            final int missingValue = Int2IntHashMap.this.missingValue;
            final int[] entries = Int2IntHashMap.this.entries;
            @DoNotSub
            final int capacity = entries.length;
            @DoNotSub
            int keyIndex = capacity;
            if (entries[capacity - 1] != missingValue) {
                for (@DoNotSub int i = 1; i < capacity; i += 2) {
                    if (entries[i] == missingValue) {
                        keyIndex = i - 1;
                        break;
                    }
                }
            }
            stopCounter = keyIndex;
            positionCounter = keyIndex + capacity;
        }

        /**
         * Returns position of the key of the current entry.
         *
         * @return key position.
         */
        @DoNotSub
        protected final int keyPosition() {
            return positionCounter & entries.length - 1;
        }

        /**
         * Number of remaining elements.
         *
         * @return number of remaining elements.
         */
        @DoNotSub
        public int remaining() {
            return remaining;
        }

        /**
         * Check if there are more elements remaining.
         *
         * @return {@code true} if {@code remaining > 0}.
         */
        public boolean hasNext() {
            return remaining > 0;
        }

        /**
         * Advance to the next entry.
         *
         * @throws NoSuchElementException if no more entries available.
         */
        protected final void findNext() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            final int[] entries = Int2IntHashMap.this.entries;
            final int missingValue = Int2IntHashMap.this.missingValue;
            @DoNotSub
            final int mask = entries.length - 1;
            for (@DoNotSub int keyIndex = positionCounter - 2; keyIndex >= stopCounter; keyIndex -= 2) {
                @DoNotSub
                final int index = keyIndex & mask;
                if (entries[index + 1] != missingValue) {
                    isPositionValid = true;
                    positionCounter = keyIndex;
                    --remaining;
                    return;
                }
            }
            isPositionValid = false;
            throw new IllegalStateException();
        }

        public void remove() {
            if (isPositionValid) {
                @DoNotSub
                final int position = keyPosition();
                entries[position + 1] = missingValue;
                --size;
                compactChain(position);
                isPositionValid = false;
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * Iterator over keys which supports access to unboxed keys via {@link #nextValue()}.
     */
    public final class KeyIterator extends AbstractIterator implements Iterator<Integer>, Serializable {

        private static final long serialVersionUID = 9151493609653852972L;

        public Integer next() {
            return nextValue();
        }

        /**
         * Return next key.
         *
         * @return next key.
         */
        public int nextValue() {
            findNext();
            return entries[keyPosition()];
        }
    }

    /**
     * Iterator over values which supports access to unboxed values.
     */
    public final class ValueIterator extends AbstractIterator implements Iterator<Integer>, Serializable {

        private static final long serialVersionUID = -5670291734793552927L;

        public Integer next() {
            return nextValue();
        }

        /**
         * Return next value.
         *
         * @return next value.
         */
        public int nextValue() {
            findNext();
            return entries[keyPosition() + 1];
        }
    }

    /**
     * Iterator over entries which supports access to unboxed keys and values.
     */
    public final class EntryIterator extends AbstractIterator implements Iterator<Entry<Integer, Integer>>, Entry<Integer, Integer>, Serializable {

        private static final long serialVersionUID = 1744408438593481051L;

        public Integer getKey() {
            return getIntKey();
        }

        /**
         * Returns the key of the current entry.
         *
         * @return the key.
         */
        public int getIntKey() {
            return entries[keyPosition()];
        }

        public Integer getValue() {
            return getIntValue();
        }

        /**
         * Returns the value of the current entry.
         *
         * @return the value.
         */
        public int getIntValue() {
            return entries[keyPosition() + 1];
        }

        public Integer setValue(final Integer value) {
            return setValue(value.intValue());
        }

        /**
         * Sets the value of the current entry.
         *
         * @param value to be set.
         * @return previous value of the entry.
         */
        public int setValue(final int value) {
            if (!isPositionValid) {
                throw new IllegalStateException();
            }
            if (missingValue == value) {
                throw new IllegalArgumentException();
            }
            @DoNotSub
            final int keyPosition = keyPosition();
            final int prevValue = entries[keyPosition + 1];
            entries[keyPosition + 1] = value;
            return prevValue;
        }

        public Entry<Integer, Integer> next() {
            findNext();
            if (shouldAvoidAllocation) {
                return this;
            }
            return allocateDuplicateEntry();
        }

        private Entry<Integer, Integer> allocateDuplicateEntry() {
            return new MapEntry(getIntKey(), getIntValue());
        }

        @DoNotSub
        public int hashCode() {
            return Integer.hashCode(getIntKey()) ^ Integer.hashCode(getIntValue());
        }

        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof Entry)) {
                return false;
            }
            final Entry<?, ?> that = (Entry<?, ?>) o;
            return Objects.equals(getKey(), that.getKey()) && Objects.equals(getValue(), that.getValue());
        }

        /**
         * An {@link java.util.Map.Entry} implementation.
         */
        public final class MapEntry implements Entry<Integer, Integer> {

            private final int k;

            private final int v;

            /**
             * Constructs entry with given key and value.
             *
             * @param k key.
             * @param v value.
             */
            public MapEntry(final int k, final int v) {
                this.k = k;
                this.v = v;
            }

            public Integer getKey() {
                return k;
            }

            public Integer getValue() {
                return v;
            }

            public Integer setValue(final Integer value) {
                return Int2IntHashMap.this.put(k, value.intValue());
            }

            @DoNotSub
            public int hashCode() {
                return Integer.hashCode(getIntKey()) ^ Integer.hashCode(getIntValue());
            }

            @DoNotSub
            public boolean equals(final Object o) {
                if (!(o instanceof Map.Entry)) {
                    return false;
                }
                final Entry<?, ?> e = (Entry<?, ?>) o;
                return (e.getKey() != null && e.getValue() != null) && (e.getKey().equals(k) && e.getValue().equals(v));
            }

            public String toString() {
                return k + "=" + v;
            }
        }
    }

    /**
     * Set of keys which supports optional cached iterators to avoid allocation.
     */
    public final class KeySet extends AbstractSet<Integer> implements Serializable {

        private static final long serialVersionUID = -7645453993079742625L;

        private final KeyIterator keyIterator = shouldAvoidAllocation ? new KeyIterator() : null;

        public KeyIterator iterator() {
            KeyIterator keyIterator = this.keyIterator;
            if (null == keyIterator) {
                keyIterator = new KeyIterator();
            }
            keyIterator.reset();
            return keyIterator;
        }

        @DoNotSub
        public int size() {
            return Int2IntHashMap.this.size();
        }

        public boolean isEmpty() {
            return Int2IntHashMap.this.isEmpty();
        }

        public void clear() {
            Int2IntHashMap.this.clear();
        }

        public boolean contains(final Object o) {
            return contains((int) o);
        }

        /**
         * Checks if key is contained in the map without boxing.
         *
         * @param key to check.
         * @return {@code true} if key is contained in this map.
         */
        public boolean contains(final int key) {
            return containsKey(key);
        }
    }

    /**
     * Collection of values which supports optionally cached iterators to avoid allocation.
     */
    public final class ValueCollection extends AbstractCollection<Integer> implements Serializable {

        private static final long serialVersionUID = -8925598924781601919L;

        private final ValueIterator valueIterator = shouldAvoidAllocation ? new ValueIterator() : null;

        public ValueIterator iterator() {
            ValueIterator valueIterator = this.valueIterator;
            if (null == valueIterator) {
                valueIterator = new ValueIterator();
            }
            valueIterator.reset();
            return valueIterator;
        }

        @DoNotSub
        public int size() {
            return Int2IntHashMap.this.size();
        }

        public boolean contains(final Object o) {
            return contains((int) o);
        }

        /**
         * Checks if the value is contained in the map.
         *
         * @param value to be checked.
         * @return  {@code true} if value is contained in this map.
         */
        public boolean contains(final int value) {
            return containsValue(value);
        }
    }

    /**
     * Set of entries which supports optionally cached iterators to avoid allocation.
     */
    public final class EntrySet extends AbstractSet<Map.Entry<Integer, Integer>> implements Serializable {

        private static final long serialVersionUID = 63641283589916174L;

        private final EntryIterator entryIterator = shouldAvoidAllocation ? new EntryIterator() : null;

        public EntryIterator iterator() {
            EntryIterator entryIterator = this.entryIterator;
            if (null == entryIterator) {
                entryIterator = new EntryIterator();
            }
            entryIterator.reset();
            return entryIterator;
        }

        @DoNotSub
        public int size() {
            return Int2IntHashMap.this.size();
        }

        public boolean isEmpty() {
            return Int2IntHashMap.this.isEmpty();
        }

        public void clear() {
            Int2IntHashMap.this.clear();
        }

        public boolean contains(final Object o) {
            if (!(o instanceof Entry)) {
                return false;
            }
            final Entry<?, ?> entry = (Entry<?, ?>) o;
            final Integer value = get(entry.getKey());
            return value != null && value.equals(entry.getValue());
        }

        public Object[] toArray() {
            return toArray(new Object[size()]);
        }

        @SuppressWarnings("unchecked")
        public <T> T[] toArray(final T[] a) {
            final T[] array = a.length >= size ? a : (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
            final EntryIterator it = iterator();
            for (@DoNotSub int i = 0; i < array.length; i++) {
                if (it.hasNext()) {
                    it.next();
                    array[i] = (T) it.allocateDuplicateEntry();
                } else {
                    array[i] = null;
                    break;
                }
            }
            return array;
        }
    }
}


List<Integer> emit(String streamId, Collection<Tuple> anchors, List<Object> tuple);

package backtype.storm.task;

import backtype.storm.tuple.Tuple;
import java.util.Collection;
import java.util.List;

public interface IOutputCollector extends IErrorReporter {

    /**
     *  Returns the task ids that received the tuples.
     */

    void emitDirect(int taskId, String streamId, Collection<Tuple> anchors, List<Object> tuple);

    void ack(Tuple input);

    void fail(Tuple input);
}


while (cause.getCause() != null && cause.getCause() != cause) {
            cause = cause.getCause();
        }

package org.traccar;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.DatagramChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.config.Keys;
import org.traccar.database.StatisticsManager;
import org.traccar.helper.DateUtil;
import org.traccar.model.Position;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

public class MainEventHandler extends ChannelInboundHandlerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(MainEventHandler.class);

    private final Set<String> connectionlessProtocols = new HashSet<>();

    private final Set<String> logAttributes = new LinkedHashSet<>();

    public MainEventHandler() {
        String connectionlessProtocolList = Context.getConfig().getString(Keys.STATUS_IGNORE_OFFLINE);
        if (connectionlessProtocolList != null) {
            connectionlessProtocols.addAll(Arrays.asList(connectionlessProtocolList.split("[, ]")));
        }
        logAttributes.addAll(Arrays.asList(Context.getConfig().getString(Keys.LOGGER_ATTRIBUTES).split("[, ]")));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof Position) {
            Position position = (Position) msg;
            try {
                Context.getDeviceManager().updateLatestPosition(position);
            } catch (SQLException error) {
                LOGGER.warn("Failed to update device", error);
            }
            String uniqueId = Context.getIdentityManager().getById(position.getDeviceId()).getUniqueId();
            StringBuilder builder = new StringBuilder();
            builder.append(formatChannel(ctx.channel())).append(" ");
            builder.append("id: ").append(uniqueId);
            for (String attribute : logAttributes) {
                switch(attribute) {
                    case "time":
                        builder.append(", time: ").append(DateUtil.formatDate(position.getFixTime(), false));
                        break;
                    case "position":
                        builder.append(", lat: ").append(String.format("%.5f", position.getLatitude()));
                        builder.append(", lon: ").append(String.format("%.5f", position.getLongitude()));
                        break;
                    case "speed":
                        if (position.getSpeed() > 0) {
                            builder.append(", speed: ").append(String.format("%.1f", position.getSpeed()));
                        }
                        break;
                    case "course":
                        builder.append(", course: ").append(String.format("%.1f", position.getCourse()));
                        break;
                    case "accuracy":
                        if (position.getAccuracy() > 0) {
                            builder.append(", accuracy: ").append(String.format("%.1f", position.getAccuracy()));
                        }
                        break;
                    case "outdated":
                        if (position.getOutdated()) {
                            builder.append(", outdated");
                        }
                        break;
                    case "invalid":
                        if (!position.getValid()) {
                            builder.append(", invalid");
                        }
                        break;
                    default:
                        Object value = position.getAttributes().get(attribute);
                        if (value != null) {
                            builder.append(", ").append(attribute).append(": ").append(value);
                        }
                        break;
                }
            }
            LOGGER.info(builder.toString());
            Main.getInjector().getInstance(StatisticsManager.class).registerMessageStored(position.getDeviceId(), position.getProtocol());
        }
    }

    private static String formatChannel(Channel channel) {
        return String.format("[%s]", channel.id().asShortText());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        if (!(ctx.channel() instanceof DatagramChannel)) {
            LOGGER.info(formatChannel(ctx.channel()) + " connected");
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        LOGGER.info(formatChannel(ctx.channel()) + " disconnected");
        closeChannel(ctx.channel());
        if (BasePipelineFactory.getHandler(ctx.pipeline(), HttpRequestDecoder.class) == null && !connectionlessProtocols.contains(ctx.pipeline().get(BaseProtocolDecoder.class).getProtocolName())) {
            Context.getConnectionManager().removeActiveDevice(ctx.channel());
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

        LOGGER.warn(formatChannel(ctx.channel()) + " error", cause);
        closeChannel(ctx.channel());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            LOGGER.info(formatChannel(ctx.channel()) + " timed out");
            closeChannel(ctx.channel());
        }
    }

    private void closeChannel(Channel channel) {
        if (!(channel instanceof DatagramChannel)) {
            channel.close();
        }
    }
}


package com.hdw.api.base.system.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.hdw.api.base.system.entity.SysRoleResource;
import java.util.List;
import java.util.Map;

/**
 * 角色资源表
 *
 * @author JacksonTu
 * @date 2018-12-11 11:35:15
 */
public interface ISysRoleResourceService extends IService<SysRoleResource> {

    /**
     * 根据角色查找菜单ID集合
     *
     * @param roleId
     * @return
     */

    void saveOrUpdateRoleResource(Long roleId, List<Long> resourceIdList);

    void deleteBatch(Long[] roleIds);

    /**
     * 自定义查询
     *
     * @param params
     * @return
     */
    List<SysRoleResource> selectResourceList(Map<String, Object> params);

    /**
     * 查询选中node
     *
     * @param roleId
     * @return
     */
    List<SysRoleResource> selectResourceNodeListByRoleId(Long roleId);
}


public TypeSignature getType() {
        return this.type;
    }

package org.spongepowered.despector.ast.insn.misc;

import static com.google.common.base.Preconditions.checkNotNull;
import org.spongepowered.despector.ast.AstVisitor;
import org.spongepowered.despector.ast.generic.TypeSignature;
import org.spongepowered.despector.ast.insn.Instruction;
import org.spongepowered.despector.ast.insn.InstructionVisitor;
import org.spongepowered.despector.util.serialization.AstSerializer;
import org.spongepowered.despector.util.serialization.MessagePacker;
import java.io.IOException;

/**
 * An instruction which casts the inner value to a specific type.
 *
 *
Example: (type) (val)

 */
public class Cast implements Instruction {

    private TypeSignature type;

    private Instruction val;

    public Cast(TypeSignature type, Instruction val) {
        this.type = checkNotNull(type, "type");
        this.val = checkNotNull(val, "val");
    }

    /**
     * Gets the type which the valye is casted to.
     */

    /**
     * Sets the type which the valye is casted to.
     */
    public void setType(TypeSignature type) {
        this.type = checkNotNull(type, "type");
    }

    /**
     * Gets the instruction for the type being cast.
     */
    public Instruction getValue() {
        return this.val;
    }

    /**
     * Sets the instruction for the type being cast.
     */
    public void setValue(Instruction val) {
        this.val = checkNotNull(val, "val");
    }

    @Override
    public TypeSignature inferType() {
        return this.type;
    }

    @Override
    public void accept(AstVisitor visitor) {
        if (visitor instanceof InstructionVisitor) {
            ((InstructionVisitor) visitor).visitCast(this);
            this.val.accept(visitor);
        }
    }

    @Override
    public void writeTo(MessagePacker pack) throws IOException {
        pack.startMap(3);
        pack.writeString("id").writeInt(AstSerializer.STATEMENT_ID_CAST);
        pack.writeString("value");
        this.val.writeTo(pack);
        pack.writeString("type");
        this.type.writeTo(pack);
        pack.endMap();
    }

    @Override
    public String toString() {
        return "((" + this.type.getName() + ") " + this.val + ")";
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Cast)) {
            return false;
        }
        Cast cast = (Cast) obj;
        return this.type.equals(cast.type) && this.val.equals(cast.val);
    }

    @Override
    public int hashCode() {
        int h = 1;
        h = h * 37 + this.type.hashCode();
        h = h * 37 + this.val.hashCode();
        return h;
    }
}


while ((n = unzip.read(buffer)) >= 0) {
            out.write(buffer, 0, n);
        }

package io.netstrap.common.tool;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * 将一串数据按照gzip方式压缩和解压缩
 *
 * @author minghu.zhang
 */
public class GzipTool {

    public static byte[] compress(byte[] data) throws IOException {
        if (data == null || data.length == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        gzip.write(data);
        gzip.close();
        return out.toByteArray();
    }

    public static byte[] compress(String data) throws IOException {
        if (data == null || data.length() == 0) {
            return null;
        }
        return compress(data.getBytes("utf-8"));
    }

    public static byte[] uncompress(byte[] data) throws IOException {
        if (data == null || data.length == 0) {
            return data;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(data);
        GZIPInputStream unzip = new GZIPInputStream(in);
        byte[] buffer = new byte[256];
        int n;

        unzip.close();
        in.close();
        return out.toByteArray();
    }

    public static String uncompress(String str) throws IOException {
        if (str == null || str.length() == 0) {
            return str;
        }
        byte[] data = uncompress(str.getBytes("utf-8"));
        return new String(data);
    }
}


public void setFifoDirectory(String fifoDirectory) {
        this.fifoDirectory = fifoDirectory;
    }

/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 *
 *******************************************************************************
 *
 *
 ******************************************************************************/
package org.pentaho.di.trans.steps.luciddbbulkloader;

import java.util.List;
import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.ProvidesDatabaseConnectionInformation;
import org.pentaho.di.core.SQLStatement;
import org.pentaho.di.core.annotations.Step;
import org.pentaho.di.core.database.Database;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.shared.SharedObjectInterface;
import org.pentaho.di.trans.DatabaseImpact;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;
import org.pentaho.metastore.api.IMetaStore;
import org.w3c.dom.Node;

/**
 * Here are the steps that we need to take to make streaming loading possible for LucidDB:

 *

 * Prerequisites:

 *

 * - Make sure we run on a server version >= 0.7.5

 * - Create an empty FIFO directory

 *

 * The following steps are carried out by the step at runtime:

 *

 * - In the FIFO directory, create a FIFO file called {tableName}.csv (using mkfifo, LINUX ONLY FOLKS!)

 * - Create a target table using standard Kettle SQL generation

 * - Create a fifo server (with a certain name) on LucidDB

 *
 *

 *    create or replace server fifo_server
 *    foreign data wrapper sys_file_wrapper
 * options (
 *     directory '/path/to/luciddb-0.7.5/fifo/',
 *     file_extension 'csv',
 *     with_header 'yes',
 *     num_rows_scan '0',
 *     lenient 'no');
 *

 *
 *

 * - Create a bulk loader file, SQL Server style: .bcp extension

 * - Execute the following SQL Command to bulk load in a separate SQL thread in the background:

 *
 *

 * insert into {schemaName}.{tableName}
 * select * from {fifoServerName}."DEFAULT"."{tableName}";
 *

 *
 *

 * - Write to the FIFO file called {tableName}.csv in the FIFO directory

 * - At the end, close the output stream to the FIFO file

 * * At the end, remove the FIFO file

 *
 * Created on 24-oct-2007

 *
 * @author Matt Casters

 */
@Step(id = "LucidDBBulkLoader", image = "BLKL.svg", i18nPackageName = "org.pentaho.di.trans.steps.luciddbbulkloader", name = "BaseStep.TypeLongDesc.LucidDBBulkLoader", description = "BaseStep.TypeTooltipDesc.LucidDBBulkLoader", categoryDescription = "i18n:org.pentaho.di.trans.step:BaseStep.Category.Deprecated")
public class LucidDBBulkLoaderMeta extends BaseStepMeta implements StepMetaInterface, ProvidesDatabaseConnectionInformation {

    // for i18n purposes, needed by Translator2!!
    private static Class<?> PKG = LucidDBBulkLoaderMeta.class;

    /**
     * what's the schema for the target?
     */
    private String schemaName;

    /**
     * what's the table for the target?
     */
    private String tableName;

    /**
     * The name of the FIFO directory to use
     */
    private String fifoDirectory;

    /**
     * The name of the FIFO server to create
     */
    private String fifoServerName;

    /**
     * database connection
     */
    private DatabaseMeta databaseMeta;

    /**
     * Field name of the target table
     */
    private String[] fieldTable;

    /**
     * Field name in the stream
     */
    private String[] fieldStream;

    /**
     * flag to indicate that the format is OK for LucidDB
     */
    private boolean[] fieldFormatOk;

    /**
     * Encoding to use
     */
    private String encoding;

    /**
     * maximum errors
     */
    private int maxErrors;

    /**
     * The number of rows to buffer before passing them over to LucidDB. This number should be non-zero since we need to
     * specify the number of rows we pass.
     */
    private String bufferSize;

    public LucidDBBulkLoaderMeta() {
        super();
    }

    /**
     * @return Returns the database.
     */
    public DatabaseMeta getDatabaseMeta() {
        return databaseMeta;
    }

    /**
     * @param database
     *          The database to set.
     */
    public void setDatabaseMeta(DatabaseMeta database) {
        this.databaseMeta = database;
    }

    /**
     * @return Returns the tableName.
     */
    public String getTableName() {
        return tableName;
    }

    /**
     * @param tableName
     *          The tableName to set.
     */
    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    /**
     * @return Returns the fieldTable.
     */
    public String[] getFieldTable() {
        return fieldTable;
    }

    /**
     * @param fieldTable
     *          The fieldTable to set.
     */
    public void setFieldTable(String[] fieldTable) {
        this.fieldTable = fieldTable;
    }

    /**
     * @return Returns the fieldStream.
     */
    public String[] getFieldStream() {
        return fieldStream;
    }

    /**
     * @param fieldStream
     *          The fieldStream to set.
     */
    public void setFieldStream(String[] fieldStream) {
        this.fieldStream = fieldStream;
    }

    public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore) throws KettleXMLException {
        readData(stepnode, databases);
    }

    public void allocate(int nrvalues) {
        fieldTable = new String[nrvalues];
        fieldStream = new String[nrvalues];
        fieldFormatOk = new boolean[nrvalues];
    }

    public Object clone() {
        LucidDBBulkLoaderMeta retval = (LucidDBBulkLoaderMeta) super.clone();
        int nrvalues = fieldTable.length;
        retval.allocate(nrvalues);
        for (int i = 0; i < nrvalues; i++) {
            retval.fieldTable[i] = fieldTable[i];
            retval.fieldStream[i] = fieldStream[i];
        }
        return retval;
    }

    private void readData(Node stepnode, List<? extends SharedObjectInterface> databases) throws KettleXMLException {
        try {
            String con = XMLHandler.getTagValue(stepnode, "connection");
            databaseMeta = DatabaseMeta.findDatabase(databases, con);
            String serror = XMLHandler.getTagValue(stepnode, "errors");
            maxErrors = Const.toInt(serror, 0);
            bufferSize = XMLHandler.getTagValue(stepnode, "buffer_size");
            schemaName = XMLHandler.getTagValue(stepnode, "schema");
            tableName = XMLHandler.getTagValue(stepnode, "table");
            fifoDirectory = XMLHandler.getTagValue(stepnode, "fifo_directory");
            fifoServerName = XMLHandler.getTagValue(stepnode, "fifo_server_name");
            encoding = XMLHandler.getTagValue(stepnode, "encoding");
            int nrvalues = XMLHandler.countNodes(stepnode, "mapping");
            allocate(nrvalues);
            for (int i = 0; i < nrvalues; i++) {
                Node vnode = XMLHandler.getSubNodeByNr(stepnode, "mapping", i);
                fieldTable[i] = XMLHandler.getTagValue(vnode, "stream_name");
                fieldStream[i] = XMLHandler.getTagValue(vnode, "field_name");
                if (fieldStream[i] == null) {
                    // default: the same name!
                    fieldStream[i] = fieldTable[i];
                }
                fieldFormatOk[i] = "Y".equalsIgnoreCase(XMLHandler.getTagValue(vnode, "field_format_ok"));
            }
        } catch (Exception e) {
            throw new KettleXMLException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML"), e);
        }
    }

    public void setDefault() {
        fieldTable = null;
        databaseMeta = null;
        maxErrors = 0;
        bufferSize = "100000";
        schemaName = "";
        tableName = BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.DefaultTableName");
        encoding = "";
        fifoDirectory = "/tmp/fifo/";
        allocate(0);
    }

    public String getXML() {
        StringBuffer retval = new StringBuffer(300);
        retval.append("    ").append(XMLHandler.addTagValue("connection", databaseMeta == null ? "" : databaseMeta.getName()));
        retval.append("    ").append(XMLHandler.addTagValue("errors", maxErrors));
        retval.append("    ").append(XMLHandler.addTagValue("buffer_size", bufferSize));
        retval.append("    ").append(XMLHandler.addTagValue("schema", schemaName));
        retval.append("    ").append(XMLHandler.addTagValue("table", tableName));
        retval.append("    ").append(XMLHandler.addTagValue("encoding", encoding));
        retval.append("    ").append(XMLHandler.addTagValue("fifo_directory", fifoDirectory));
        retval.append("    ").append(XMLHandler.addTagValue("fifo_server_name", fifoServerName));
        for (int i = 0; i < fieldTable.length; i++) {
            retval.append("      <mapping>").append(Const.CR);
            retval.append("        ").append(XMLHandler.addTagValue("stream_name", fieldTable[i]));
            retval.append("        ").append(XMLHandler.addTagValue("field_name", fieldStream[i]));
            retval.append("        ").append(XMLHandler.addTagValue("field_format_ok", fieldFormatOk[i]));
            retval.append("      </mapping>").append(Const.CR);
        }
        return retval.toString();
    }

    public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases) throws KettleException {
        try {
            databaseMeta = rep.loadDatabaseMetaFromStepAttribute(id_step, "id_connection", databases);
            maxErrors = (int) rep.getStepAttributeInteger(id_step, "errors");
            bufferSize = rep.getStepAttributeString(id_step, "buffer_size");
            schemaName = rep.getStepAttributeString(id_step, "schema");
            tableName = rep.getStepAttributeString(id_step, "table");
            encoding = rep.getStepAttributeString(id_step, "encoding");
            fifoDirectory = rep.getStepAttributeString(id_step, "fifo_directory");
            fifoServerName = rep.getStepAttributeString(id_step, "fifo_server_name");
            int nrvalues = rep.countNrStepAttributes(id_step, "stream_name");
            allocate(nrvalues);
            for (int i = 0; i < nrvalues; i++) {
                fieldTable[i] = rep.getStepAttributeString(id_step, i, "stream_name");
                fieldStream[i] = rep.getStepAttributeString(id_step, i, "field_name");
                if (fieldStream[i] == null) {
                    fieldStream[i] = fieldTable[i];
                }
                fieldFormatOk[i] = rep.getStepAttributeBoolean(id_step, i, "field_format_ok");
            }
        } catch (Exception e) {
            throw new KettleException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.UnexpectedErrorReadingStepInfoFromRepository"), e);
        }
    }

    public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step) throws KettleException {
        try {
            rep.saveDatabaseMetaStepAttribute(id_transformation, id_step, "id_connection", databaseMeta);
            rep.saveStepAttribute(id_transformation, id_step, "errors", maxErrors);
            rep.saveStepAttribute(id_transformation, id_step, "buffer_size", bufferSize);
            rep.saveStepAttribute(id_transformation, id_step, "schema", schemaName);
            rep.saveStepAttribute(id_transformation, id_step, "table", tableName);
            rep.saveStepAttribute(id_transformation, id_step, "encoding", encoding);
            rep.saveStepAttribute(id_transformation, id_step, "fifo_directory", fifoDirectory);
            rep.saveStepAttribute(id_transformation, id_step, "fifo_server_name", fifoServerName);
            for (int i = 0; i < fieldTable.length; i++) {
                rep.saveStepAttribute(id_transformation, id_step, i, "stream_name", fieldTable[i]);
                rep.saveStepAttribute(id_transformation, id_step, i, "field_name", fieldStream[i]);
                rep.saveStepAttribute(id_transformation, id_step, i, "field_format_ok", fieldFormatOk[i]);
            }
            // Also, save the step-database relationship!
            if (databaseMeta != null) {
                rep.insertStepDatabase(id_transformation, id_step, databaseMeta.getObjectId());
            }
        } catch (Exception e) {
            throw new KettleException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.UnableToSaveStepInfoToRepository") + id_step, e);
        }
    }

    public void getFields(RowMetaInterface rowMeta, String origin, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException {
        // Default: nothing changes to rowMeta
    }

    public void check(List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore) {
        CheckResult cr;
        String error_message = "";
        if (databaseMeta != null) {
            Database db = new Database(loggingObject, databaseMeta);
            db.shareVariablesWith(transMeta);
            try {
                db.connect();
                if (!Utils.isEmpty(tableName)) {
                    cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.TableNameOK"), stepMeta);
                    remarks.add(cr);
                    boolean first = true;
                    boolean error_found = false;
                    error_message = "";
                    // Check fields in table
                    String schemaTable = databaseMeta.getQuotedSchemaTableCombination(transMeta.environmentSubstitute(schemaName), transMeta.environmentSubstitute(tableName));
                    RowMetaInterface r = db.getTableFields(schemaTable);
                    if (r != null) {
                        cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.TableExists"), stepMeta);
                        remarks.add(cr);
                        // How about the fields to insert/dateMask in the table?
                        first = true;
                        error_found = false;
                        error_message = "";
                        for (int i = 0; i < fieldTable.length; i++) {
                            String field = fieldTable[i];
                            ValueMetaInterface v = r.searchValueMeta(field);
                            if (v == null) {
                                if (first) {
                                    first = false;
                                    error_message += BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.MissingFieldsToLoadInTargetTable") + Const.CR;
                                }
                                error_found = true;
                                error_message += "\t\t" + field + Const.CR;
                            }
                        }
                        if (error_found) {
                            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta);
                        } else {
                            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.AllFieldsFoundInTargetTable"), stepMeta);
                        }
                        remarks.add(cr);
                    } else {
                        error_message = BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.CouldNotReadTableInfo");
                        cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta);
                        remarks.add(cr);
                    }
                }
                // Look up fields in the input stream <prev>
                if (prev != null && prev.size() > 0) {
                    cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.StepReceivingDatas", prev.size() + ""), stepMeta);
                    remarks.add(cr);
                    boolean first = true;
                    error_message = "";
                    boolean error_found = false;
                    for (int i = 0; i < fieldStream.length; i++) {
                        ValueMetaInterface v = prev.searchValueMeta(fieldStream[i]);
                        if (v == null) {
                            if (first) {
                                first = false;
                                error_message += BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.MissingFieldsInInput") + Const.CR;
                            }
                            error_found = true;
                            error_message += "\t\t" + fieldStream[i] + Const.CR;
                        }
                    }
                    if (error_found) {
                        cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta);
                    } else {
                        cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.AllFieldsFoundInInput"), stepMeta);
                    }
                    remarks.add(cr);
                } else {
                    error_message = BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.MissingFieldsInInput3") + Const.CR;
                    cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta);
                    remarks.add(cr);
                }
            } catch (KettleException e) {
                error_message = BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.DatabaseErrorOccurred") + e.getMessage();
                cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta);
                remarks.add(cr);
            } finally {
                db.disconnect();
            }
        } else {
            error_message = BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.InvalidConnection");
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta);
            remarks.add(cr);
        }
        // See if we have input streams leading to this step!
        if (input.length > 0) {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.StepReceivingInfoFromOtherSteps"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.CheckResult.NoInputError"), stepMeta);
            remarks.add(cr);
        }
    }

    public SQLStatement getSQLStatements(TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, Repository repository, IMetaStore metaStore) throws KettleStepException {
        SQLStatement retval = new SQLStatement(stepMeta.getName(), databaseMeta, null);
        if (databaseMeta != null) {
            if (prev != null && prev.size() > 0) {
                // Copy the row
                RowMetaInterface tableFields = new RowMeta();
                // Now change the field names
                for (int i = 0; i < fieldTable.length; i++) {
                    ValueMetaInterface v = prev.searchValueMeta(fieldStream[i]);
                    if (v != null) {
                        ValueMetaInterface tableField = v.clone();
                        tableField.setName(fieldTable[i]);
                        tableFields.addValueMeta(tableField);
                    } else {
                        throw new KettleStepException("Unable to find field [" + fieldStream[i] + "] in the input rows");
                    }
                }
                if (!Utils.isEmpty(tableName)) {
                    Database db = new Database(loggingObject, databaseMeta);
                    db.shareVariablesWith(transMeta);
                    try {
                        db.connect();
                        String schemaTable = databaseMeta.getQuotedSchemaTableCombination(transMeta.environmentSubstitute(schemaName), transMeta.environmentSubstitute(tableName));
                        String sql = db.getDDL(schemaTable, tableFields, null, false, null, true);
                        if (Utils.isEmpty(sql)) {
                            retval.setSQL(null);
                        } else {
                            retval.setSQL(sql);
                        }
                    } catch (KettleException e) {
                        retval.setError(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.GetSQL.ErrorOccurred") + e.getMessage());
                    }
                } else {
                    retval.setError(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.GetSQL.NoTableDefinedOnConnection"));
                }
            } else {
                retval.setError(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.GetSQL.NotReceivingAnyFields"));
            }
        } else {
            retval.setError(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.GetSQL.NoConnectionDefined"));
        }
        return retval;
    }

    public void analyseImpact(List<DatabaseImpact> impact, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, Repository repository, IMetaStore metaStore) throws KettleStepException {
        if (prev != null) {
            /* DEBUG CHECK THIS */
            // Insert dateMask fields : read/write
            for (int i = 0; i < fieldTable.length; i++) {
                ValueMetaInterface v = prev.searchValueMeta(fieldStream[i]);
                DatabaseImpact ii = new DatabaseImpact(DatabaseImpact.TYPE_IMPACT_READ_WRITE, transMeta.getName(), stepMeta.getName(), databaseMeta.getDatabaseName(), transMeta.environmentSubstitute(tableName), fieldTable[i], fieldStream[i], v != null ? v.getOrigin() : "?", "", "Type = " + v.toStringMeta());
                impact.add(ii);
            }
        }
    }

    public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans trans) {
        return new LucidDBBulkLoader(stepMeta, stepDataInterface, cnr, transMeta, trans);
    }

    public StepDataInterface getStepData() {
        return new LucidDBBulkLoaderData();
    }

    public DatabaseMeta[] getUsedDatabaseConnections() {
        if (databaseMeta != null) {
            return new DatabaseMeta[] { databaseMeta };
        } else {
            return super.getUsedDatabaseConnections();
        }
    }

    public RowMetaInterface getRequiredFields(VariableSpace space) throws KettleException {
        String realTableName = space.environmentSubstitute(tableName);
        String realSchemaName = space.environmentSubstitute(schemaName);
        if (databaseMeta != null) {
            Database db = new Database(loggingObject, databaseMeta);
            try {
                db.connect();
                if (!Utils.isEmpty(realTableName)) {
                    String schemaTable = databaseMeta.getQuotedSchemaTableCombination(realSchemaName, realTableName);
                    if (db.checkTableExists(schemaTable)) {
                        return db.getTableFields(schemaTable);
                    } else {
                        throw new KettleException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.TableNotFound"));
                    }
                } else {
                    throw new KettleException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.TableNotSpecified"));
                }
            } catch (Exception e) {
                throw new KettleException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.ErrorGettingFields"), e);
            } finally {
                db.disconnect();
            }
        } else {
            throw new KettleException(BaseMessages.getString(PKG, "LucidDBBulkLoaderMeta.Exception.ConnectionNotDefined"));
        }
    }

    /**
     * @return the schemaName
     */
    public String getSchemaName() {
        return schemaName;
    }

    /**
     * @param schemaName
     *          the schemaName to set
     */
    public void setSchemaName(String schemaName) {
        this.schemaName = schemaName;
    }

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public String getDelimiter() {
        return ",";
    }

    public String getEnclosure() {
        return "\"";
    }

    public int getMaxErrors() {
        return maxErrors;
    }

    public void setMaxErrors(int maxErrors) {
        this.maxErrors = maxErrors;
    }

    /**
     * @return the bufferSize
     */
    public String getBufferSize() {
        return bufferSize;
    }

    /**
     * @param bufferSize
     *          the bufferSize to set
     */
    public void setBufferSize(String bufferSize) {
        this.bufferSize = bufferSize;
    }

    /**
     * @return the fieldFormatOk
     */
    public boolean[] getFieldFormatOk() {
        return fieldFormatOk;
    }

    /**
     * @param fieldFormatOk
     *          the fieldFormatOk to set
     */
    public void setFieldFormatOk(boolean[] fieldFormatOk) {
        this.fieldFormatOk = fieldFormatOk;
    }

    /**
     * @return the fifoServerName
     */
    public String getFifoServerName() {
        return fifoServerName;
    }

    /**
     * @param fifoServerName
     *          the fifoServerName to set
     */
    public void setFifoServerName(String fifoServerName) {
        this.fifoServerName = fifoServerName;
    }

    /**
     * @return the fifoDirectory
     */
    public String getFifoDirectory() {
        return fifoDirectory;
    }

    /**
     * @param fifoDirectory
     *          the fifoDirectory to set
     */

    @Override
    public String getMissingDatabaseConnectionInformationMessage() {
        // TODO Auto-generated method stub
        return null;
    }
}