Browse Source

rename: Bitmask into MaskFactory
new: MaskSet
rename: UserStore#match into #find
fix: local build does not require javadoc
new: scripts & pmd rules

Ranides Atterwim 4 năm trước cách đây
mục cha
commit
f7de2a6b4f

+ 0 - 213
assira.core/src/main/java/net/ranides/assira/collection/sets/Bitmask.java

@@ -1,213 +0,0 @@
-/*
- * @author Ranides Atterwim {@literal <ranides@gmail.com>}
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.collection.sets;
-
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.function.ToIntFunction;
-import net.ranides.assira.collection.arrays.ArrayUtils;
-
-/**
- *
- * @author Ranides Atterwim {@literal <ranides@gmail.com>}
- */
-public class Bitmask<T> {
-    
-    private static final String NO_ELEMENT = "Stored value can't be mapped to any constant: ";
-    
-    final T[] universe;
-    final ToIntFunction<T> function;
-    final int usedbits;
-    final Class<T> type;
-
-    @SuppressWarnings({"PMD.ArrayIsStoredDirectly", "unchecked"})
-    public Bitmask(T[] universe, ToIntFunction<T> function) {
-        this.universe = ArrayUtils.copy(universe);
-        this.function = function;
-        this.type = (Class<T>)universe.getClass().getComponentType();
-        int sum = 0;
-        for(T item : universe) {
-            sum |= function.applyAsInt(item);
-        }
-        this.usedbits = sum;
-    }
-    
-    @SafeVarargs
-    public final Set<T> constant(T... values) {
-        return new CSet<>(this, mask(values));
-    }
-    
-    public final Set<T> constant(int value) {
-        if(value != (value & usedbits)) {
-            throw new IllegalArgumentException(NO_ELEMENT + Integer.toHexString(value));
-        }
-        return new CSet<>(this, value);
-    }
-    
-    @SafeVarargs
-    public final Set<T> collect(T... values) {
-        return new VSet<>(this, mask(values));
-    }
-    
-    public Set<T> collect(int value) {
-        if(value != (value & usedbits)) {
-            throw new IllegalArgumentException(NO_ELEMENT + Integer.toHexString(value));
-        }
-        return new VSet<>(this, value);
-    }
-    
-    private int mask(T[] values) {
-        int mask = 0;
-        for(T item : values) {
-            mask |= function.applyAsInt(item);
-        }
-        return mask;
-    }
-    
-    private int o2int(Object object) {
-        return t2int(type.cast(object));
-    }
-    
-    private int t2int(T object) {
-        return function.applyAsInt(object);
-    }
-
-    public Set<T> clone(Set<T> values) {
-        if(values instanceof CSet<?>) {
-            CSet<T> that = (CSet<T>)values;
-            return new VSet<>(that.factory, that.values);
-        }
-        VSet<T> ret = new VSet<>(this, 0);
-        ret.addAll(values);
-        return ret;
-    }
-    
-    private static class CSet<T> extends AbstractSet<T> {
-        
-        protected final Bitmask<T> factory;
-        
-        protected int values;
-
-        public CSet(Bitmask<T> factory, int values) {
-            this.factory = factory;
-            this.values = values;
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return factory.new PIterator(values);
-        }
-
-        @Override
-        public int size() {
-            return Integer.bitCount(values);
-        }
-
-        @Override
-        public boolean contains(Object object) {
-            if(!factory.type.isInstance(object)) {
-                return false;
-            }
-            int v = factory.o2int(object);
-            return v == (values & v);
-        }
-
-        @Override
-        public boolean containsAll(Collection<?> object) {
-            if(object instanceof CSet) {
-                CSet<?> that = (CSet<?>)object;
-                return (this.factory == that.factory) && (that.values == (this.values &that.values));
-            }
-            return super.containsAll(object);
-        }
-        
-    }
-        
-    private static final class VSet<T> extends CSet<T> {
-        
-        public VSet(Bitmask<T> factory, int values) {
-            super(factory, values);
-        }
-
-        @Override
-        public boolean remove(Object value) {
-            if(!factory.type.isInstance(value)) {
-                return false;
-            }
-            
-            int iv = factory.o2int(value);
-            if(0 == (values & iv)) {
-                return false;
-            }
-            values &= ~iv;
-            return true;
-        }
-
-        @Override
-        public boolean add(T value) {
-            return iadd(factory.t2int(value));
-        }
-
-        @Override
-        public boolean addAll(Collection<? extends T> object) {
-            if(object instanceof CSet) {
-                CSet<?> that = (CSet<?>)object;
-                if(this.factory == that.factory) {
-                    return iadd(that.values);
-                }
-            }
-            return super.addAll(object);
-        }
-        
-        private boolean iadd(int iv) {
-            if(iv == (values & iv)) {
-                return false;
-            }
-            values |= iv;
-            return true;
-        }
-        
-    }
-    
-    private final class PIterator implements Iterator<T> {
-        
-        private int value;
-        private int index;
-
-        public PIterator(int value) {
-            this.value = value;
-            this.index = 0;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return 0 != value;
-        }
-
-        @Override
-        public T next() {
-            try {
-                while(value!=0) {
-                    T item = universe[index++];
-                    int iv = t2int(item);
-                    if( 0 != (value & iv) ) {
-                        value &= ~iv;
-                        return item;
-                    }
-                }
-            } catch(IndexOutOfBoundsException cause) {
-                throw new NoSuchElementException(NO_ELEMENT + Integer.toHexString(value));
-            }
-            throw new NoSuchElementException();
-        }
-        
-    }
-    
-}

+ 178 - 0
assira.core/src/main/java/net/ranides/assira/collection/sets/MaskFactory.java

@@ -0,0 +1,178 @@
+/*
+ * @author Ranides Atterwim {@literal <ranides@gmail.com>}
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.sets;
+
+import java.util.Set;
+import java.util.function.ToIntFunction;
+import net.ranides.assira.collection.arrays.ArrayUtils;
+import net.ranides.assira.collection.sets.MaskSet.ImmutableSet;
+import net.ranides.assira.collection.sets.MaskSet.MutableSet;
+
+/**
+ * This class can be used as static mapper of int values into set of predefined values.
+ *
+ * At construction time, you specify predefined type and mapping functions which
+ * associates int value with every predefined value. Later you can use this instance
+ * as factory which creates MaskSet from integer or vice versa.
+ *
+ * Preferably, int values assigned to T constants should be stored in different bits,
+ * if you want predictable mapping. Whats more, preferred type for MaskFactory is some enum type,
+ * which offers closed list of possible values.
+ *
+ * Every set returned by factory stores its content inside just one int.
+ * Please note, that because of that, maximal number of distinct values is 32.
+ *
+ * @author Ranides Atterwim {@literal <ranides@gmail.com>}
+ */
+public class MaskFactory<T> {
+
+    static final String NO_ELEMENT = "Stored value can't be mapped to any constant: ";
+
+    final T[] universe;
+    final ToIntFunction<T> function;
+    final int usedbits;
+    final Class<T> type;
+
+    /**
+     * Creates new factory for specified enum type.
+     * Mapping function should returns distinct value for every enum value, preferably distinct bit.
+     *
+     * @param universe list of enum values
+     * @param function mapping
+     */
+    @SuppressWarnings({"PMD.ArrayIsStoredDirectly", "unchecked"})
+    public MaskFactory(T[] universe, ToIntFunction<T> function) {
+        this.universe = ArrayUtils.copy(universe);
+        this.function = function;
+        this.type = (Class<T>)universe.getClass().getComponentType();
+        int sum = 0;
+        for(T item : universe) {
+            sum |= function.applyAsInt(item);
+        }
+        this.usedbits = sum;
+    }
+
+    /**
+     * Creates immutable set with specified enum values.
+     * Returned set uses bitwise operations and stores content in just one int.
+     *
+     * @param values values
+     * @return immutable mask
+     */
+    @SafeVarargs
+    public final MaskSet<T> constant(T... values) {
+        return new ImmutableSet<>(this, mask(values));
+    }
+
+    /**
+     * Converts integer into immutable set with specified enum values.
+     * Extracts information about content using mapping function associated with this factory.
+     * Returned set uses bitwise operations and stores content in just one int.
+     *
+     * @param value value
+     * @return immutable mask
+     */
+    public final MaskSet<T> constant(int value) {
+        if(value != (value & usedbits)) {
+            throw new IllegalArgumentException(unknownValueMessage(value));
+        }
+        return new ImmutableSet<>(this, value);
+    }
+
+    /**
+     * Creates mutable set with specified enum values.
+     * Returned set uses bitwise operations and stores content in just one int.
+     *
+     * @param values values
+     * @return mutable mask
+     */
+    @SafeVarargs
+    public final MaskSet<T> collect(T... values) {
+        return new MutableSet<>(this, mask(values));
+    }
+
+    /**
+     * Converts integer into mutable set with specified enum values.
+     * Extracts information about content using mapping function associated with this factory.
+     * Returned set uses bitwise operations and stores content in just one int.
+     *
+     * @param value value
+     * @return mutable mask
+     */
+    public MaskSet<T> collect(int value) {
+        if(value != (value & usedbits)) {
+            throw new IllegalArgumentException(unknownValueMessage(value));
+        }
+        return new MutableSet<>(this, value);
+    }
+
+    /**
+     * Converts set of enum values into integer representation.
+     * Converts values into int using mapping function associated with this factory.
+     *
+     * @param values values
+     * @return int
+     */
+    public int valueOf(Set<T> values) {
+        int out = 0;
+        for(T value : values) {
+            out |= function.applyAsInt(value);
+        }
+        return out;
+    }
+
+    /**
+     * Converts list of enum values into integer representation.
+     * Converts values into int using mapping function associated with this factory.
+     *
+     * @param values values
+     * @return int
+     */
+    @SafeVarargs
+    public final int valueOf(T... values) {
+        int out = 0;
+        for(T value : values) {
+            out |= function.applyAsInt(value);
+        }
+        return out;
+    }
+
+    /**
+     * Creates new mutable set with the same values as in provided set.
+     * Returned set uses bitwise operations and stores content in just one int.
+     *
+     * @param values values
+     * @return mutable mask
+     */
+    public MaskSet<T> clone(Set<T> values) {
+        if(values instanceof MaskSet<?>) {
+            return ((MaskSet<T>)values).toMutable();
+        }
+        return new MutableSet<>(this, valueOf(values));
+    }
+
+    private int mask(T[] values) {
+        int mask = 0;
+        for(T item : values) {
+            mask |= function.applyAsInt(item);
+        }
+        return mask;
+    }
+
+    int objectToInt(Object object) {
+        return function.applyAsInt(type.cast(object));
+    }
+
+    int genericToInt(T object) {
+        return function.applyAsInt(object);
+    }
+
+    String unknownValueMessage(int value) {
+        return NO_ELEMENT + Integer.toHexString(value);
+    }
+
+}

+ 0 - 3
deploy-asm.bat

@@ -1,3 +0,0 @@
-@echo off
-call jdk8
-call mvn clean deploy -P asm,release

+ 3 - 0
scripts/deploy-asm.bat

@@ -0,0 +1,3 @@
+@echo off
+call jdk8
+call mvn %* deploy -P asm,release