+
+ /**
+ * Populates an XML model of the feature colour scheme for one feature type
+ *
+ * @param featureType
+ * @param fcol
+ * @return
+ */
+ protected static jalview.schemabinding.version2.Colour marshalColour(
+ String featureType, FeatureColourI fcol)
+ {
+ jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
+ if (fcol.isSimpleColour())
+ {
+ col.setRGB(Format.getHexString(fcol.getColour()));
+ }
+ else
+ {
+ col.setRGB(Format.getHexString(fcol.getMaxColour()));
+ col.setMin(fcol.getMin());
+ col.setMax(fcol.getMax());
+ col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
+ col.setAutoScale(fcol.isAutoScaled());
+ col.setThreshold(fcol.getThreshold());
+ col.setColourByLabel(fcol.isColourByLabel());
+ col.setThreshType(fcol.isAboveThreshold() ? ColourThreshTypeType.ABOVE
+ : (fcol.isBelowThreshold() ? ColourThreshTypeType.BELOW
+ : ColourThreshTypeType.NONE));
+ if (fcol.isColourByAttribute())
+ {
+ col.setAttributeName(fcol.getAttributeName());
+ }
+ Color noColour = fcol.getNoColour();
+ if (noColour == null)
+ {
+ col.setNoValueColour(NoValueColour.NONE);
+ }
+ else if (noColour == fcol.getMaxColour())
+ {
+ col.setNoValueColour(NoValueColour.MAX);
+ }
+ else
+ {
+ col.setNoValueColour(NoValueColour.MIN);
+ }
+ }
+ col.setName(featureType);
+ return col;
+ }
+
+ /**
+ * Populates an XML model of the feature filter(s) for one feature type
+ *
+ * @param firstMatcher
+ * the first (or only) match condition)
+ * @param filter
+ * remaining match conditions (if any)
+ * @param and
+ * if true, conditions are and-ed, else or-ed
+ */
+ protected static MatcherSet marshalFilter(FeatureMatcherI firstMatcher,
+ Iterator<FeatureMatcherI> filters, boolean and)
+ {
+ MatcherSet result = new MatcherSet();
+
+ if (filters.hasNext())
+ {
+ /*
+ * compound matcher
+ */
+ CompoundMatcher compound = new CompoundMatcher();
+ compound.setAnd(and);
+ MatcherSet matcher1 = marshalFilter(firstMatcher,
+ Collections.emptyIterator(), and);
+ compound.addMatcherSet(matcher1);
+ FeatureMatcherI nextMatcher = filters.next();
+ MatcherSet matcher2 = marshalFilter(nextMatcher, filters, and);
+ compound.addMatcherSet(matcher2);
+ result.setCompoundMatcher(compound);
+ }
+ else
+ {
+ /*
+ * single condition matcher
+ */
+ MatchCondition matcherModel = new MatchCondition();
+ matcherModel.setCondition(
+ firstMatcher.getMatcher().getCondition().getStableName());
+ matcherModel.setValue(firstMatcher.getMatcher().getPattern());
+ if (firstMatcher.isByAttribute())
+ {
+ matcherModel.setBy(FeatureMatcherByType.BYATTRIBUTE);
+ matcherModel.setAttributeName(firstMatcher.getAttribute());
+ }
+ else if (firstMatcher.isByLabel())
+ {
+ matcherModel.setBy(FeatureMatcherByType.BYLABEL);
+ }
+ else if (firstMatcher.isByScore())
+ {
+ matcherModel.setBy(FeatureMatcherByType.BYSCORE);
+ }
+ result.setMatchCondition(matcherModel);
+ }
+
+ return result;
+ }
+
+ /**
+ * Loads one XML model of a feature filter to a Jalview object
+ *
+ * @param featureType
+ * @param matcherSetModel
+ * @return
+ */
+ protected static FeatureMatcherSetI unmarshalFilter(
+ String featureType, MatcherSet matcherSetModel)
+ {
+ FeatureMatcherSetI result = new FeatureMatcherSet();
+ try
+ {
+ unmarshalFilterConditions(result, matcherSetModel, true);
+ } catch (IllegalStateException e)
+ {
+ // mixing AND and OR conditions perhaps
+ System.err.println(
+ String.format("Error reading filter conditions for '%s': %s",
+ featureType, e.getMessage()));
+ // return as much as was parsed up to the error
+ }
+
+ return result;
+ }
+
+ /**
+ * Adds feature match conditions to matcherSet as unmarshalled from XML
+ * (possibly recursively for compound conditions)
+ *
+ * @param matcherSet
+ * @param matcherSetModel
+ * @param and
+ * if true, multiple conditions are AND-ed, else they are OR-ed
+ * @throws IllegalStateException
+ * if AND and OR conditions are mixed
+ */
+ protected static void unmarshalFilterConditions(
+ FeatureMatcherSetI matcherSet, MatcherSet matcherSetModel,
+ boolean and)
+ {
+ MatchCondition mc = matcherSetModel.getMatchCondition();
+ if (mc != null)
+ {
+ /*
+ * single condition
+ */
+ FeatureMatcherByType filterBy = mc.getBy();
+ Condition cond = Condition.fromString(mc.getCondition());
+ String pattern = mc.getValue();
+ FeatureMatcherI matchCondition = null;
+ if (filterBy == FeatureMatcherByType.BYLABEL)
+ {
+ matchCondition = FeatureMatcher.byLabel(cond, pattern);
+ }
+ else if (filterBy == FeatureMatcherByType.BYSCORE)
+ {
+ matchCondition = FeatureMatcher.byScore(cond, pattern);
+
+ }
+ else if (filterBy == FeatureMatcherByType.BYATTRIBUTE)
+ {
+ String[] attNames = mc.getAttributeName();
+ matchCondition = FeatureMatcher.byAttribute(cond, pattern,
+ attNames);
+ }
+
+ /*
+ * note this throws IllegalStateException if AND-ing to a
+ * previously OR-ed compound condition, or vice versa
+ */
+ if (and)
+ {
+ matcherSet.and(matchCondition);
+ }
+ else
+ {
+ matcherSet.or(matchCondition);
+ }
+ }
+ else
+ {
+ /*
+ * compound condition
+ */
+ MatcherSet[] matchers = matcherSetModel.getCompoundMatcher()
+ .getMatcherSet();
+ boolean anded = matcherSetModel.getCompoundMatcher().getAnd();
+ if (matchers.length == 2)
+ {
+ unmarshalFilterConditions(matcherSet, matchers[0], anded);
+ unmarshalFilterConditions(matcherSet, matchers[1], anded);
+ }
+ else
+ {
+ System.err.println("Malformed compound filter condition");
+ }
+ }
+ }
+
+ /**
+ * Loads one XML model of a feature colour to a Jalview object
+ *
+ * @param colourModel
+ * @return
+ */
+ protected static FeatureColourI unmarshalColour(
+ jalview.schemabinding.version2.Colour colourModel)
+ {
+ FeatureColourI colour = null;
+
+ if (colourModel.hasMax())
+ {
+ Color mincol = null;
+ Color maxcol = null;
+ Color noValueColour = null;
+
+ try
+ {
+ mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
+ maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
+ } catch (Exception e)
+ {
+ Cache.log.warn("Couldn't parse out graduated feature color.", e);
+ }
+
+ NoValueColour noCol = colourModel.getNoValueColour();
+ if (noCol == NoValueColour.MIN)
+ {
+ noValueColour = mincol;
+ }
+ else if (noCol == NoValueColour.MAX)
+ {
+ noValueColour = maxcol;
+ }
+
+ colour = new FeatureColour(mincol, maxcol, noValueColour,
+ colourModel.getMin(),
+ colourModel.getMax());
+ String[] attributes = colourModel.getAttributeName();
+ if (attributes != null && attributes.length > 0)
+ {
+ colour.setAttributeName(attributes);
+ }
+ if (colourModel.hasAutoScale())
+ {
+ colour.setAutoScaled(colourModel.getAutoScale());
+ }
+ if (colourModel.hasColourByLabel())
+ {
+ colour.setColourByLabel(colourModel.getColourByLabel());
+ }
+ if (colourModel.hasThreshold())
+ {
+ colour.setThreshold(colourModel.getThreshold());
+ }
+ ColourThreshTypeType ttyp = colourModel.getThreshType();
+ if (ttyp != null)
+ {
+ if (ttyp == ColourThreshTypeType.ABOVE)
+ {
+ colour.setAboveThreshold(true);
+ }
+ else if (ttyp == ColourThreshTypeType.BELOW)
+ {
+ colour.setBelowThreshold(true);
+ }
+ }
+ }
+ else
+ {
+ Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
+ colour = new FeatureColour(color);
+ }
+
+ return colour;
+ }