package org.molgenis.data.rest.v2; import org.springframework.core.convert.converter.Converter; class AttributeFilterConverter implements Converter<String, AttributeFilter> { @Override public AttributeFilter convert(String source) { AttributeFilter attributeFilter = new AttributeFilter(); parseAttributeFilter(source, 0, attributeFilter); return attributeFilter; } private int parseAttributeFilter(String source, int offset, AttributeFilter attrFilter) { boolean escaped = false; int nrChars = source.length(); StringBuilder strBuilder = new StringBuilder(); int i = offset; for (; i < nrChars; ++i) { char c = source.charAt(i); if (!escaped) { switch (c) { case '\\': escaped = true; break; case ',': if (!strBuilder.toString().isEmpty()) { addFilter(attrFilter, strBuilder.toString()); strBuilder.setLength(0); } break; // TODO support slash as alternative for parenthesis with one element // case '/': // AttributeFilter nestedAttributeFilter = new AttributeFilter(); // parseAttributeFilter(source, i + 1, nestedAttributeFilter); // strBuilder.setLength(0); // break; case '(': AttributeFilter nestedAttributeFilter = new AttributeFilter(); i = parseAttributeFilter(source, i + 1, nestedAttributeFilter); addFilter(attrFilter, strBuilder.toString(), nestedAttributeFilter); strBuilder.setLength(0); break; case ')': if (!strBuilder.toString().isEmpty()) { attrFilter.add(strBuilder.toString()); } return i; case '*': attrFilter.setIncludeAllAttrs(true); break; default: strBuilder.append(c); if (i == nrChars - 1) { addFilter(attrFilter, strBuilder.toString()); } break; } } else { strBuilder.append(c); escaped = false; } } return i; } private void addFilter(AttributeFilter attrFilter, String attrName) { addFilter(attrFilter, attrName, null); } private void addFilter(AttributeFilter attrFilter, String attrName, AttributeFilter nestedAttrFilter) { if (attrName.equals("~id")) { attrFilter.setIncludeIdAttr(true, nestedAttrFilter); } else if (attrName.equals("~lbl")) { attrFilter.setIncludeLabelAttr(true, nestedAttrFilter); } else { attrFilter.add(attrName, nestedAttrFilter); } } }