Преглед изворни кода

change: MathStats#deviation
fix: tests

Ranides Atterwim пре 3 година
родитељ
комит
b7a5025398

+ 1 - 1
assira.commons/src/main/java/net/ranides/assira/collection/Grid.java

@@ -339,7 +339,7 @@ public class Grid<T> {
     }
 
     /**
-     * GridHeader is essentially CQuery<String> backed by list, but with opitimized lookup by name.
+     * GridHeader is essentially {@code CQuery<String>} backed by list, but with opitimized lookup by name.
      * Method "indexOf(name)" will return in constant time.
      */
     public class GridHeader extends CQueryAbstract<String> {

+ 46 - 15
assira.commons/src/main/java/net/ranides/assira/math/MathStats.java

@@ -8,6 +8,7 @@ import net.ranides.assira.collection.query.CQuery;
 import net.ranides.assira.generic.CompareUtils;
 
 import java.util.DoubleSummaryStatistics;
+import java.util.IntSummaryStatistics;
 import java.util.List;
 
 /**
@@ -31,8 +32,17 @@ public class MathStats {
      * @param data input
      * @return standard deviation stats
      */
-    public static StandardDeviation deviation(CQuery<? extends Number> data) {
-        return new StandardDeviation(data);
+    public static DoubleDeviationSummary deviation(CQuery<? extends Number> data) {
+        return new DoubleDeviationSummary(data);
+    }
+
+    /**
+     * Traverses whole input and calculates average, variance and deviation
+     * @param data input
+     * @return standard deviation stats
+     */
+    public static IntDeviationSummary deviation(int... data) {
+        return new IntDeviationSummary(CQuery.from().array(data).map(Integer.class));
     }
 
     /**
@@ -111,12 +121,7 @@ public class MathStats {
      * Basic statistics about classical average
      */
     @Data
-    public static class StandardDeviation {
-
-        /**
-         * classic arithmetical average
-         */
-        private final double average;
+    public static class DoubleDeviationSummary extends DoubleSummaryStatistics {
 
         /**
          * classic variance
@@ -128,19 +133,45 @@ public class MathStats {
          */
         private final double deviation;
 
-        private StandardDeviation(CQuery<? extends Number> data) {
-            DoubleSummaryStatistics statAvg = data.stream()
-                    .mapToDouble(Number::doubleValue)
-                    .summaryStatistics();
-
-            double avg = statAvg.getAverage();
+        private DoubleDeviationSummary(CQuery<? extends Number> data) {
+            combine(data.stream().mapToDouble(Number::doubleValue).summaryStatistics());
 
+            double avg = getAverage();
             DoubleSummaryStatistics statVar = data.stream()
                     .mapToDouble(Number::doubleValue)
                     .map(x -> MathUtils.square(avg - x))
                     .summaryStatistics();
 
-            this.average = statAvg.getAverage();
+            this.variance = statVar.getAverage();
+            this.deviation = Math.sqrt(statVar.getAverage());
+        }
+    }
+
+    /**
+     * Basic statistics about classical average
+     */
+    @Data
+    public static class IntDeviationSummary extends IntSummaryStatistics {
+
+        /**
+         * classic variance
+         */
+        private final double variance;
+
+        /**
+         * classic standard deviation
+         */
+        private final double deviation;
+
+        private IntDeviationSummary(CQuery<? extends Number> data) {
+            combine(data.stream().mapToInt(Number::intValue).summaryStatistics());
+
+            double avg = getAverage();
+            DoubleSummaryStatistics statVar = data.stream()
+                .mapToInt(Number::intValue)
+                .mapToDouble(x -> MathUtils.square(avg - x))
+                .summaryStatistics();
+
             this.variance = statVar.getAverage();
             this.deviation = Math.sqrt(statVar.getAverage());
         }

+ 1 - 1
assira.core/src/main/java/net/ranides/assira/collection/iterators/IntIterator.java

@@ -10,7 +10,7 @@ import java.util.Iterator;
 
 /**
  * Interface identical to generic Iterator, but avoiding boxing operations.
- * It provides default implementations of methods required by Iterator<Integer>
+ * It provides default implementations of methods required by {@code Iterator<Integer>}
  *
  * IntInterator can be used as ordinary iterator, but it offers methods for working with primitive values.
  */

+ 1 - 1
assira.core/src/main/java/net/ranides/assira/collection/iterators/IntListIterator.java

@@ -10,7 +10,7 @@ import java.util.ListIterator;
 
 /**
  * Interface identical to generic ListIterator, but avoiding boxing operations.
- * It provides default implementations of methods required by ListIterator<Integer>
+ * It provides default implementations of methods required by {@code ListIterator<Integer>}
  *
  * IntInterator can be used as ordinary iterator, but it offers methods for working with primitive values.
  *

+ 2 - 2
assira.core/src/main/java/net/ranides/assira/collection/lists/NativeArrayList.java

@@ -23,10 +23,10 @@ import net.ranides.assira.collection.arrays.NativeArray;
  * This will return singleton list with one element of type int[]
  *
  * You can use #wrap methods to create correct list:
- * NativeArrayList.wrap(new char[]{'a','b','c'}) will return List<Character>
+ * NativeArrayList.wrap(new char[]{'a','b','c'}) will return {@code List<Character>}
  *
  * Please note, that we can't return correct generic type because of Java limitations: you have to
- * make unchecked cast from List<Object> on your own, or use unsafe methods like $wrap
+ * make unchecked cast from {@code List<Object>} on your own, or use unsafe methods like $wrap
  *
  * There is one special ovveride for int[] arrays, because we have specialized IntList interface.
  *

+ 4 - 0
assira.core/src/main/java/net/ranides/assira/collection/query/CQuery.java

@@ -460,6 +460,10 @@ public interface CQuery<T> extends Iterable<T> {
      */
     <R> CQuery<R> map(Function<? super T,R> f);
 
+    <R> CQuery<R> map(Class<R> f);
+
+    <R> CQuery<R> map(IClass<R> f);
+
     /**
      * Returns query which calculates new value for every item.
      * If function returns "empty" then value is discarded.

+ 10 - 0
assira.core/src/main/java/net/ranides/assira/collection/query/CQueryAbstract.java

@@ -337,6 +337,16 @@ public abstract class CQueryAbstract<T> implements CQuery<T>, CQueryFeatures {
         return new CQMap<>(this, f);
     }
 
+    @Override
+    public <R> CQuery<R> map(Class<R> f) {
+        return map(f::cast);
+    }
+
+    @Override
+    public <R> CQuery<R> map(IClass<R> f) {
+        return map(f::cast);
+    }
+
     @Override
     public <R> CQuery<R> mapOptional(Function<? super T, Optional<R>> f) {
         return new CQMapOptional<>(this, f);

+ 23 - 3
assira.core/src/main/java/net/ranides/assira/xml/XMLContext.java

@@ -7,17 +7,37 @@
 package net.ranides.assira.xml;
 
 /**
+ * XMLContext is used by {@link XMLSelector} predicate.
+ * Every node passed to selector is wrapped by this class, because we want to know both node and its position.
+ * Selectors can use "index" for example to filter even/odd elements.
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public interface XMLContext {
-    
+
+    /**
+     * Returns current node passed to {@link XMLSelector} for test/evaluation.
+     *
+     * @return XMLElement
+     */
     XMLElement node();
-    
+
+    /**
+     * Returns current node passed to {@link XMLSelector} for test/evaluation.
+     * More precisely: it returns collection with one node.
+     *
+     * @return XMLElements
+     */
     default XMLElements nodes() {
         return XMLElements.of(node());
     }
-    
+
+    /**
+     * Returns index of current node.
+     * Index is the position of this node inside "children" list used by its parent.
+     *
+     * @return int
+     */
     int index();
     
 }

+ 94 - 10
assira.core/src/main/java/net/ranides/assira/xml/XMLDocument.java

@@ -9,29 +9,113 @@ package net.ranides.assira.xml;
 import org.w3c.dom.Document;
 
 /**
+ * XMLDocument allows you to create detached XML nodes, associated with it.
+ * Detached nodes can be inserted anywhere into parse tree.
+ *
+ * This class does not represent root node of XML document.
+ * To obtain root element, please use {@link #root} or {@link #node}
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public interface XMLDocument {
-    
+
+    /**
+     * Interoperability method: returns "org.w3c.dom.Document"
+     *
+     * @return this
+     */
     Document node();
-    
+
+    /**
+     * Returns root element of this document
+     *
+     * @return XMLElement
+     */
+    XMLElement root();
+
+    /**
+     * Creates new attribute element.
+     *
+     * Attribute nodes can be inserted into collection returned by {@link XMLElement#attrs()}.
+     * You can set attribute value by calling {@link XMLElement#text(String)} on returned element.
+     *
+     * @param name name
+     * @return XMLElement
+     */
     XMLElement attr(String name);
-    
+
+    /**
+     * Creates new CDATA element with specified content.
+     *
+     * CDATA nodes can be inserted to any tag node using {@link XMLElement#append}
+     *
+     * @param value value
+     * @return XMLElement
+     */
     XMLElement cdata(String value);
-    
+
+    /**
+     * Creates new comment section with specified content.
+     *
+     * CDATA nodes can be inserted to any tag node using {@link XMLElement#append}
+     *
+     * @param value value
+     * @return XMLElement
+     */
     XMLElement comment(String value);
-    
+
+    /**
+     * Creates new empty document fragment.
+     *
+     * Fragments can be inserted to any tag node using {@link XMLElement#append}
+     * Insertion of fragment causes direct insertion of its children, not container itself.
+     *
+     * @return XMLElement
+     */
     XMLElement fragment();
-    
+
+    /**
+     * Creates new document fragment with children defined by "xml" markup.
+     *
+     * Fragments can be inserted to any tag node using {@link XMLElement#append}
+     * Insertion of fragment causes direct insertion of its children, not container itself.
+     *
+     * @param xml xml
+     * @return XMLElement
+     */
     XMLElement fragment(String xml);
-    
+
+    /**
+     * Creates new tag with specified name.
+     *
+     * Tag nodes can be inserted to any tag node using {@link XMLElement#append}
+     *
+     * @param tag tag
+     * @return XMLElement
+     */
     XMLElement tag(String tag);
-    
+
     XMLElement entity(String name);
-    
+
+    /**
+     * Creates new processing instruction with specified content.
+     *
+     * Processing instructions can be prepended before root tag
+     *
+     * @param target target
+     * @param value value
+     * @return XMLElement
+     */
     XMLElement processing(String target, String value);
-    
+
+    /**
+     * Creates new text node. Escapes all special characters, for example &amp; &lt; &gt;
+     *
+     * Text nodes can be inserted to any tag node using {@link XMLElement#append}
+     *
+     * @param value value
+     * @return XMLElement
+     */
     XMLElement text(String value);
     
 }

+ 58 - 8
assira.core/src/main/java/net/ranides/assira/xml/XMLElement.java

@@ -22,6 +22,9 @@ import net.ranides.assira.xml.impl.W3Element;
 import org.w3c.dom.Node;
 
 /**
+ * XMLElement offer interface similar to JQuery
+ *
+ * You can use static factory methods to wrap "org.w3c.dom" nodes or load documents.
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
@@ -32,30 +35,72 @@ import org.w3c.dom.Node;
 })
 public interface XMLElement extends Wrapper<String> {
 
-    static XMLElement fromNode(Node doc) {
-        return W3Element.wrap(doc);
+    /**
+     * Wraps "org.w3c.dom" node
+     *
+     * @param node node
+     * @return XMLElement
+     */
+    static XMLElement fromNode(Node node) {
+        return W3Element.wrap(node);
     }
-    
+
+    /**
+     * Parses XML markup from "doc" string.
+     *
+     * @param doc doc
+     * @return XMLElement
+     */
     static XMLElement fromString(String doc) {
         return W3ElementFactory.fromString(new StringReader(doc));
     }
-    
+
+    /**
+     * Parses XML document from file
+     *
+     * @param doc doc
+     * @return XMLElement
+     */
     static XMLElement fromFile(File doc) {
         return W3ElementFactory.fromFile(doc);
     }
 
+    /**
+     * Parses XML document from file
+     *
+     * @param doc doc
+     * @return XMLElement
+     */
     static XMLElement fromPath(Path doc) {
         return W3ElementFactory.fromPath(doc);
     }
-    
+
+    /**
+     * Parses XML document from file
+     *
+     * @param doc doc
+     * @return XMLElement
+     */
     static XMLElement fromURI(URI doc) {
         return W3ElementFactory.fromURI(doc);
     }
-    
+
+    /**
+     * Parses XML document from reader
+     *
+     * @param doc doc
+     * @return XMLElement
+     */
     static XMLElement fromReader(Reader doc) {
         return W3ElementFactory.fromString(doc);
     }
-    
+
+    /**
+     * Parses XML document from stream
+     *
+     * @param doc doc
+     * @return XMLElement
+     */
     static XMLElement fromStream(InputStream doc) {
         return W3ElementFactory.fromStream(doc);
     }
@@ -65,7 +110,12 @@ public interface XMLElement extends Wrapper<String> {
     XMLElement root();
     
     XMLType nodetype();
-    
+
+    /**
+     * Interoperability method: returns "org.w3c.dom.Node"
+     *
+     * @return this
+     */
     Node node();
     
     String name();

+ 1 - 1
assira.core/src/main/java/net/ranides/assira/xml/XMLOptions.java

@@ -41,7 +41,7 @@ public enum XMLOptions {
     INDENT(OutputKeys.INDENT),
     
     /**
-     * The non-standard property key to use to set the
+     * The non-standard property key used to set the
      * number of whitepaces to indent by, per indentation level,
      * if indent="yes".
      */

+ 2 - 1
assira.core/src/main/java/net/ranides/assira/xml/XMLWriter.java

@@ -23,7 +23,8 @@ public interface XMLWriter {
     XMLWriter save(OutputStream ostream) throws IOException;
 
     XMLWriter save(Writer writer) throws IOException;
-    
+
+    @Override
     String toString();
     
     XMLWriter param(XMLOptions param, String value);

+ 6 - 0
assira.core/src/main/java/net/ranides/assira/xml/impl/W3Document.java

@@ -9,6 +9,7 @@ package net.ranides.assira.xml.impl;
 import net.ranides.assira.generic.CompareUtils;
 import net.ranides.assira.xml.XMLDocument;
 import net.ranides.assira.xml.XMLElement;
+import net.ranides.assira.xml.XMLType;
 import org.w3c.dom.Document;
 
 /**
@@ -28,6 +29,11 @@ public class W3Document implements XMLDocument {
         return doc;
     }
 
+    @Override
+    public XMLElement root() {
+        return new W3Element(node()).children(XMLType.ELEMENT).first();
+    }
+
     @Override
     public XMLElement attr(String name) {
         return new W3Element(doc.createAttribute(name));

+ 1 - 3
assira.core/src/test/resources/xml/doc-jdk8.xml

@@ -9,7 +9,5 @@
         <h1>header</h1>
         <p>paragraph</p>
         <span>summary</span>
-        <span>hello world!</span>
-        hello &lt;b&gt; &amp;custom;!
-    </body>
+        <span>hello world!</span>hello &lt;b&gt; &amp;custom;!</body>
 </target><!--hello world--><!--comment--><?EOF meta-eof?>

+ 2 - 2
assira.junit/src/main/java/net/ranides/assira/junit/TestContract.java

@@ -26,10 +26,10 @@ import java.lang.annotation.Target;
  * 1) just an object of type T:
  *    runner will create it using supplier and send this object in default state to the tester
  *
- * 2) supplier of object of type Supplier<T>:
+ * 2) supplier of object of type {@code Supplier<T>}:
  *    runner will pass supplier, tester can call supplier to create many objects with default state
  *
- * 3) function<X,T>:
+ * 3) {@code function<X,T>}:
  *    runner will pass function; tester can call this function with different "X" arguments
  *    to create objects in different state. there is no exact definition of "different state":
  *    only guaranteed effect is, they won't be equal.