+ StringTokenizer gcol = new StringTokenizer(descriptor, BAR, true);
+ float min = Float.MIN_VALUE;
+ float max = Float.MAX_VALUE;
+ boolean byLabel = false;
+ boolean byAttribute = false;
+ String attName = null;
+ String mincol = null;
+ String maxcol = null;
+
+ /*
+ * first token should be 'label', or 'score', or an
+ * attribute name, or simple colour, or minimum colour
+ */
+ String nextToken = gcol.nextToken();
+ if (nextToken == BAR)
+ {
+ throw new IllegalArgumentException(
+ "Expected either 'label' or a colour specification in the line: "
+ + descriptor);
+ }
+ if (nextToken.toLowerCase().startsWith(LABEL))
+ {
+ byLabel = true;
+ // get the token after the next delimiter:
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ }
+ else if (nextToken.toLowerCase().startsWith(SCORE))
+ {
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ }
+ else if (nextToken.toLowerCase().startsWith(ATTRIBUTE))
+ {
+ byAttribute = true;
+ attName = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ attName = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ }
+ else
+ {
+ mincol = nextToken;
+ }
+
+ /*
+ * if only one token, it can validly be label, attributeName,
+ * or a plain colour value
+ */
+ if (!gcol.hasMoreTokens())
+ {
+ if (byLabel || byAttribute)
+ {
+ FeatureColourI fc = new FeatureColour();
+ fc.setColourByLabel(true);
+ if (byAttribute)
+ {
+ fc.setAttributeName(
+ FeatureMatcher.fromAttributeDisplayName(attName));
+ }
+ return fc;
+ }
+
+ Color colour = ColorUtils.parseColourString(descriptor);
+ if (colour == null)
+ {
+ throw new IllegalArgumentException(
+ "Invalid colour descriptor: " + descriptor);
+ }
+ return new FeatureColour(colour);
+ }
+
+ /*
+ * continue parsing for min/max/no colour (if graduated)
+ * and for threshold (colour by text or graduated)
+ */
+
+ /*
+ * autoScaled == true: colours range over actual score range
+ * autoScaled == false ('abso'): colours range over min/max range
+ */
+ boolean autoScaled = true;
+ String tok = null, minval, maxval;
+ String noValueColour = NO_VALUE_MIN;
+
+ if (mincol != null)
+ {
+ // at least four more tokens
+ if (mincol.equals(BAR))
+ {
+ mincol = null;
+ }
+ else
+ {
+ gcol.nextToken(); // skip next '|'
+ }
+ maxcol = gcol.nextToken();
+ if (maxcol.equals(BAR))
+ {
+ maxcol = null;
+ }
+ else
+ {
+ gcol.nextToken(); // skip next '|'
+ }
+ tok = gcol.nextToken();
+
+ /*
+ * check for specifier for colour for no attribute value
+ * (new in 2.11, defaults to minColour if not specified)
+ */
+ if (tok.equalsIgnoreCase(NO_VALUE_MIN))
+ {
+ tok = gcol.nextToken();
+ tok = gcol.nextToken();
+ }
+ else if (tok.equalsIgnoreCase(NO_VALUE_MAX))
+ {
+ noValueColour = NO_VALUE_MAX;
+ tok = gcol.nextToken();
+ tok = gcol.nextToken();
+ }
+ else if (tok.equalsIgnoreCase(NO_VALUE_NONE))
+ {
+ noValueColour = NO_VALUE_NONE;
+ tok = gcol.nextToken();
+ tok = gcol.nextToken();
+ }
+
+ gcol.nextToken(); // skip next '|'
+ if (tok.toLowerCase().startsWith(ABSOLUTE))
+ {
+ minval = gcol.nextToken();
+ gcol.nextToken(); // skip next '|'
+ autoScaled = false;
+ }
+ else
+ {
+ minval = tok;
+ }
+ maxval = gcol.nextToken();
+ if (gcol.hasMoreTokens())
+ {
+ gcol.nextToken(); // skip next '|'
+ }
+ try
+ {
+ if (minval.length() > 0)
+ {
+ min = new Float(minval).floatValue();
+ }
+ } catch (Exception e)
+ {
+ throw new IllegalArgumentException(
+ "Couldn't parse the minimum value for graduated colour ('"
+ + minval + "')");
+ }
+ try
+ {
+ if (maxval.length() > 0)
+ {
+ max = new Float(maxval).floatValue();
+ }
+ } catch (Exception e)
+ {
+ throw new IllegalArgumentException(
+ "Couldn't parse the maximum value for graduated colour ("
+ + descriptor + ")");
+ }
+ }
+ else
+ {
+ /*
+ * dummy min/max colours for colour by text
+ * (label or attribute value)
+ */
+ mincol = "white";
+ maxcol = "black";
+ byLabel = true;
+ }
+
+ /*
+ * construct the FeatureColour!
+ */
+ FeatureColour featureColour;
+ try
+ {
+ Color minColour = ColorUtils.parseColourString(mincol);
+ Color maxColour = ColorUtils.parseColourString(maxcol);
+ Color noColour = noValueColour.equals(NO_VALUE_MAX) ? maxColour
+ : (noValueColour.equals(NO_VALUE_NONE) ? null : minColour);
+ featureColour = new FeatureColour(maxColour, minColour, maxColour,
+ noColour, min, max);
+ featureColour.setColourByLabel(minColour == null);
+ featureColour.setAutoScaled(autoScaled);
+ if (byAttribute)
+ {
+ featureColour.setAttributeName(
+ FeatureMatcher.fromAttributeDisplayName(attName));
+ }
+ // add in any additional parameters
+ String ttype = null, tval = null;
+ if (gcol.hasMoreTokens())
+ {
+ // threshold type and possibly a threshold value
+ ttype = gcol.nextToken();
+ if (ttype.toLowerCase().startsWith(BELOW))
+ {
+ featureColour.setBelowThreshold(true);
+ }
+ else if (ttype.toLowerCase().startsWith(ABOVE))
+ {
+ featureColour.setAboveThreshold(true);
+ }
+ else
+ {
+ if (!ttype.toLowerCase().startsWith("no"))
+ {
+ System.err.println(
+ "Ignoring unrecognised threshold type : " + ttype);
+ }
+ }
+ }
+ if (featureColour.hasThreshold())
+ {
+ try
+ {
+ gcol.nextToken();
+ tval = gcol.nextToken();
+ featureColour.setThreshold(new Float(tval).floatValue());
+ } catch (Exception e)
+ {
+ System.err.println("Couldn't parse threshold value as a float: ("
+ + tval + ")");
+ }
+ }
+ if (gcol.hasMoreTokens())
+ {
+ System.err.println(
+ "Ignoring additional tokens in parameters in graduated colour specification\n");
+ while (gcol.hasMoreTokens())
+ {
+ System.err.println(BAR + gcol.nextToken());
+ }
+ System.err.println("\n");
+ }
+ return featureColour;
+ } catch (Exception e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }