]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/util/Range.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / Range.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/Range.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/Range.java
new file mode 100644 (file)
index 0000000..4488ed7
--- /dev/null
@@ -0,0 +1,322 @@
+/*******************************************************************************\r
+ *  Copyright (c) 2010 Association for Decentralized Information Management in\r
+ *  Industry THTH ry.\r
+ *  All rights reserved. This program and the accompanying materials\r
+ *  are made available under the terms of the Eclipse Public License v1.0\r
+ *  which accompanies this distribution, and is available at\r
+ *  http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ *  Contributors:\r
+ *      VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.util;
+
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+
+
+
+/**
+ * Number range.
+ *  
+ * Examples:
+ *     Inclusive "[0..100]"
+ *  Exclusive "[0..100)"
+ *  Unlimited "[..]"
+ *  No upper limit "[0..)"
+ *  No lower limit "(..0]"
+ *  Exact value "0"
+ *  Exclude all "()"
+ *
+ *     Inclusive "[0.5..100.5]"
+ *  Exclusive "[0.5..100.5)"
+ *  Unlimited "[..]"
+ *  No upper limit "[0.5..)"
+ *  No lower limit "(..0.5]"
+ *  Exact value "[0.5]"
+ *  
+ *     Inclusive "[0e..100]"
+ *  Exclusive "[0..100)"
+ *  Unlimited ""
+ *  No upper limit "[0..)"
+ *  No lower limit "(..0]"
+ *  Exact value "0"
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class Range {
+       
+       Limit lower; 
+       Limit upper; 
+
+       public static Range create(Byte lower, Byte upper, boolean lowerInclusive, boolean upperInclusive)
+       {
+               Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
+               Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
+               return new Range(ll, ul);
+       }
+       
+       public static Range create(Integer lower, Integer upper, boolean lowerInclusive, boolean upperInclusive)
+       {
+               Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
+               Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
+               return new Range(ll, ul);
+       }
+
+       public static Range create(Long lower, Long upper, boolean lowerInclusive, boolean upperInclusive)
+       {
+               Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
+               Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
+               return new Range(ll, ul);
+       }
+       
+       public static Range create(Float lower, Float upper, boolean lowerInclusive, boolean upperInclusive)
+       {
+               Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
+               Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
+               return new Range(ll, ul);
+       }
+       
+       public static Range create(Double lower, Double upper, boolean lowerInclusive, boolean upperInclusive)
+       {
+               Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
+               Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
+               return new Range(ll, ul);
+       }
+
+       public static Range create(Byte exact)
+       {
+               Limit l = Limit.inclusive(exact);
+               return new Range(l, l);
+       }       
+       
+       public static Range create(Integer exact)
+       {
+               Limit l = Limit.inclusive(exact);
+               return new Range(l, l);
+       }       
+       
+       public static Range create(Long exact)
+       {
+               Limit l = Limit.inclusive(exact);
+               return new Range(l, l);
+       }       
+       
+       public static Range create(Float exact)
+       {
+               Limit l = Limit.inclusive(exact);
+               return new Range(l, l);
+       }       
+       
+       public static Range create(Double exact)
+       {
+               Limit l = Limit.inclusive(exact);
+               return new Range(l, l);
+       }       
+
+       public static Range includeAll()
+       {
+               Limit l = Limit.nolimit();
+               return new Range(l, l);
+       }
+       
+       public static Range excludeAll()
+       {
+               Limit l = Limit.exclusive(0);
+               return new Range(l, l);
+       }
+       
+       public static Range between(Limit limit1, Limit limit2) {
+               Number l = limit1.getValue();
+               Number u = limit2.getValue();
+               if (l!=null && u!=null) {
+                       if (NumberComparator.INSTANCE.compare(l, u)<0)
+                               return new Range(limit2, limit1);
+               }
+               return new Range(limit1, limit2);
+       }
+       
+       public Range(Limit lower, Limit upper)
+       {
+               this.lower = lower;
+               this.upper = upper;
+               
+               // Ensure lower < upper
+               Number l = lower.getValue();
+               Number u = upper.getValue();
+               if (l!=null && u!=null) {
+                       if (NumberComparator.INSTANCE.compare(l, u)<0)
+                               throw new IllegalArgumentException("Lower limit must be less-or-equal to upper limit");
+               }
+
+               // Exact value
+               if (l!=null && u!=null && l.equals(u)) {                        
+                       if (lower.isExclusive() || upper.isExclusive())
+                               this.lower = this.upper = Limit.exclusive(0);
+               }
+               
+       }
+
+       public Limit getLower() {
+               return lower;
+       }
+       
+       public Limit getUpper() {
+               return upper;
+       }
+       
+       @Override
+       public String toString() {
+               if (lower instanceof Limit.Nolimit && upper instanceof Limit.Nolimit) return "[..]";
+                               
+               // Range
+               StringBuilder sb = new StringBuilder();
+                               
+               
+               Number l = lower.getValue();
+               Number u = upper.getValue();
+               
+               if (l!=null && u!=null && l.equals(u))
+               {
+                       if (lower.isExclusive() || upper.isExclusive())
+                               return "()";
+                       
+                       // Exact value
+                       return l.toString();
+               }
+               
+               sb.append( !lower.isInclusive() ? '(' : "[" );
+               // Range
+               if (lower instanceof Limit.Nolimit == false) sb.append( l );
+               sb.append( ".." );
+               if (upper instanceof Limit.Nolimit == false) sb.append( u );
+               sb.append( !upper.isInclusive() ? ')' : "]" );
+               
+               return sb.toString();
+       }
+
+       /**
+        * Double pattern
+        * 
+        * This pattern is not perfect as it accepts strings such as
+        * "e0", "", and ".", but its good enough as Double class does the final
+        * parsing. 
+        */
+//     static Pattern DOUBLE_PATTERN = Pattern.compile("-?+\\d*(?:\\.\\d*)?(?:[eE]\\d++)?");   
+       static Pattern RANGE_PATTERN = Pattern.compile(
+               "(?:([\\(\\[])(-?\\d*(?:\\.\\d*)?(?:[eE]-?\\d+)?)??\\.\\.(-?\\d*(?:\\.\\d*)?(?:[eE]-?\\d+)?)??([\\)\\]]))|"+ // [x..y] [x..y) (x..y)
+               "(-?+\\d*(?:\\.\\d*)?(?:[eE]-?\\d+)?)|"+ // x
+               "\\(\\)"); // () 
+       
+       public static Range valueOfUnchecked(String txt) {              
+               try {
+                       return valueOf(txt);
+               } catch (RangeException e) {
+                       throw new IllegalArgumentException(e);
+               }
+       }
+
+       public static Range valueOf(String txt) 
+       throws RangeException
+       {\r
+               Matcher m = RANGE_PATTERN.matcher(txt);
+               if (!m.matches()) throw new RangeException("Illegal range '" + txt + "'");
+               
+               if ( (m.group(1)!=null) || (m.group(2)!=null) || (m.group(3)!=null) || (m.group(4)!=null) ) {
+                       
+                       Limit l1, l2;
+                       if (m.group(2)==null && m.group(3)==null) {
+                               return new Range(Limit.nolimit(), Limit.nolimit());
+                       } else if (m.group(2)==null) {
+                               l1 = Limit.nolimit();
+                       } else {
+                               try {
+                                       Long l = Long.parseLong( m.group(2) );
+                                       l1 = m.group(1).equals("[") ? Limit.inclusive(l) : Limit.exclusive(l);
+                               } catch (NumberFormatException nfe) {
+                                       try {
+                                               Double d = Double.parseDouble( m.group(2) );
+                                               l1 = m.group(1).equals("[") ? Limit.inclusive(d) : Limit.exclusive(d);
+                                       } catch (NumberFormatException e) {
+                                               throw new RangeException(e);
+                                       }
+                               }
+                       }
+
+                       if (m.group(3)==null) {
+                               l2 = Limit.nolimit();
+                       } else {
+                               try {
+                                       Long l = Long.parseLong( m.group(3) );
+                                       l2 = m.group(4).equals("]") ? Limit.inclusive(l) : Limit.exclusive(l);
+                               } catch (NumberFormatException nfe) {
+                                       try {\r
+                                               Double d = Double.parseDouble( m.group(3) );
+                                               l2 = m.group(4).equals("]") ? Limit.inclusive(d) : Limit.exclusive(d);
+                                       } catch (NumberFormatException e) {
+                                               throw new RangeException(e);
+                                       }
+                               }
+                       }
+                       
+                       return new Range(l1, l2);
+               }
+               
+               if ( (m.group(5)!=null) ) {                     
+                       try {
+                               Long l = Long.parseLong( m.group(5) );
+                               Limit l1 = Limit.inclusive(l);
+                               return new Range(l1, l1);
+                       } catch (NumberFormatException nfe) {
+                               try {
+                                       Double d = Double.parseDouble( m.group(5) );
+                                       Limit l1 = Limit.inclusive(d);
+                                       return new Range(l1, l1);
+                               } catch (NumberFormatException e) {
+                                       throw new RangeException(e);
+                               }
+                       }
+               }
+               
+               Range result = new Range(Limit.exclusive(0), Limit.exclusive(0));
+               return result;
+       }
+       
+       @Override
+       public boolean equals(Object obj) {
+               if (obj instanceof Range == false) return false;
+               Range other = (Range) obj;
+               return 
+                       ( other.upper == null ? upper == null : other.upper.equals( upper ) ) &&
+                       ( other.lower == null ? lower == null : other.lower.equals( lower ) );
+       }
+       
+       @Override
+       public int hashCode() {
+               return 
+                       ObjectUtils.hashCode(upper) * 13 +
+                       ObjectUtils.hashCode(lower);
+       }
+       
+       public boolean contains(Number value)
+       {
+               if (lower instanceof Limit.Nolimit==false) 
+               {
+                       int compare = NumberComparator.INSTANCE.compare(lower.getValue(), value);
+                       if (compare==0 && lower.isExclusive()) return false;
+                       if (compare<0) return false;
+               }
+                               
+               if (upper instanceof Limit.Nolimit==false) 
+               {
+                       int compare = NumberComparator.INSTANCE.compare(upper.getValue(), value);
+                       if (compare==0 && upper.isExclusive()) return false;
+                       if (compare>0) return false;
+               }
+               
+               return true;
+       }
+       
+       
+}
+