diff options
author | Jon Bratseth <bratseth@oath.com> | 2018-01-31 17:36:21 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@oath.com> | 2018-01-31 17:36:21 +0100 |
commit | c56889931e1547a6a6db420a3c886ddf03f5bd6e (patch) | |
tree | a718a9bbacf236c54c8164def703f4e108e7287d /container-search/src/main/java/com/yahoo/search | |
parent | 2c25a02adbe644b3f50dc44252c6b61974d0c8d6 (diff) |
Canonicalize features
This allows us to find the type of features referenced in
ranking expressions regardless of the form they are written in.
Diffstat (limited to 'container-search/src/main/java/com/yahoo/search')
-rw-r--r-- | container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileXMLReader.java | 229 |
1 files changed, 119 insertions, 110 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileXMLReader.java b/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileXMLReader.java index 095d83d2887..eb4a0ad6be4 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileXMLReader.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileXMLReader.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.logging.Logger; /** * A class which imports query profiles and types from XML files @@ -30,8 +29,6 @@ import java.util.logging.Logger; */ public class QueryProfileXMLReader { - private static Logger logger=Logger.getLogger(QueryProfileXMLReader.class.getName()); - /** * Reads all query profile xml files in a given directory, * and all type xml files from the immediate subdirectory "types/" (if any) @@ -42,8 +39,8 @@ public class QueryProfileXMLReader { List<NamedReader> queryProfileReaders = new ArrayList<>(); List<NamedReader> queryProfileTypeReaders = new ArrayList<>(); try { - File dir=new File(directory); - if ( !dir.isDirectory() ) throw new IllegalArgumentException("Could not read query profiles: '" + + File dir = new File(directory); + if ( ! dir.isDirectory() ) throw new IllegalArgumentException("Could not read query profiles: '" + directory + "' is not a valid directory."); for (File file : sortFiles(dir)) { @@ -100,21 +97,20 @@ public class QueryProfileXMLReader { } public List<Element> createQueryProfileTypes(List<NamedReader> queryProfileTypeReaders, QueryProfileTypeRegistry registry) { - List<Element> queryProfileTypeElements=new ArrayList<>(queryProfileTypeReaders.size()); + List<Element> queryProfileTypeElements = new ArrayList<>(queryProfileTypeReaders.size()); for (NamedReader reader : queryProfileTypeReaders) { - Element root=XML.getDocument(reader).getDocumentElement(); + Element root = XML.getDocument(reader).getDocumentElement(); if ( ! root.getNodeName().equals("query-profile-type")) { - logger.info("Ignoring '" + reader.getName() + - "': Expected XML root element 'query-profile-type' but was '" + root.getNodeName() + "'"); - continue; + throw new IllegalArgumentException("Root tag in '" + reader.getName() + + "' must be 'query-profile-type', not '" + root.getNodeName() + "'"); } String idString=root.getAttribute("id"); - if (idString==null || idString.equals("")) + if (idString == null || idString.equals("")) throw new IllegalArgumentException("'" + reader.getName() + "' has no 'id' attribute in the root element"); - ComponentId id=new ComponentId(idString); + ComponentId id = new ComponentId(idString); validateFileNameToId(reader.getName(),id,"query profile type"); - QueryProfileType type=new QueryProfileType(id); + QueryProfileType type = new QueryProfileType(id); type.setMatchAsPath(XML.getChild(root,"match") != null); type.setStrict(XML.getChild(root,"strict") != null); registry.register(type); @@ -124,32 +120,33 @@ public class QueryProfileXMLReader { } public List<Element> createQueryProfiles(List<NamedReader> queryProfileReaders, QueryProfileRegistry registry) { - List<Element> queryProfileElements=new ArrayList<>(queryProfileReaders.size()); + List<Element> queryProfileElements = new ArrayList<>(queryProfileReaders.size()); for (NamedReader reader : queryProfileReaders) { - Element root=XML.getDocument(reader).getDocumentElement(); + Element root = XML.getDocument(reader).getDocumentElement(); if ( ! root.getNodeName().equals("query-profile")) { - logger.info("Ignoring '" + reader.getName() + - "': Expected XML root element 'query-profile' but was '" + root.getNodeName() + "'"); - continue; + throw new IllegalArgumentException("Root tag in '" + reader.getName() + + "' must be 'query-profile', not '" + root.getNodeName() + "'"); } - String idString=root.getAttribute("id"); - if (idString==null || idString.equals("")) - throw new IllegalArgumentException("Query profile '" + reader.getName() + "' has no 'id' attribute in the root element"); - ComponentId id=new ComponentId(idString); - validateFileNameToId(reader.getName(),id,"query profile"); - - QueryProfile queryProfile=new QueryProfile(id); - String typeId=root.getAttribute("type"); - if (typeId!=null && ! typeId.equals("")) { - QueryProfileType type=registry.getType(typeId); - if (type==null) - throw new IllegalArgumentException("Query profile '" + reader.getName() + "': Type id '" + typeId + "' can not be resolved"); + String idString = root.getAttribute("id"); + if (idString == null || idString.equals("")) + throw new IllegalArgumentException("Query profile '" + reader.getName() + + "' has no 'id' attribute in the root element"); + ComponentId id = new ComponentId(idString); + validateFileNameToId(reader.getName(), id, "query profile"); + + QueryProfile queryProfile = new QueryProfile(id); + String typeId = root.getAttribute("type"); + if (typeId != null && ! typeId.equals("")) { + QueryProfileType type = registry.getType(typeId); + if (type == null) + throw new IllegalArgumentException("Query profile '" + reader.getName() + + "': Type id '" + typeId + "' can not be resolved"); queryProfile.setType(type); } - Element dimensions=XML.getChild(root,"dimensions"); - if (dimensions!=null) + Element dimensions = XML.getChild(root,"dimensions"); + if (dimensions != null) queryProfile.setDimensions(toArray(XML.getValue(dimensions))); registry.register(queryProfile); @@ -159,66 +156,72 @@ public class QueryProfileXMLReader { } /** Throws an exception if the name is not corresponding to the id */ - private void validateFileNameToId(final String actualName,ComponentId id,String artifactName) { - String expectedCanonicalFileName=id.toFileName(); - String expectedAlternativeFileName=id.stringValue().replace(":","-").replace("/","_"); // legacy - String fileName=new File(actualName).getName(); - fileName=stripXmlEnding(fileName); - String canonicalFileName=ComponentId.fromFileName(fileName).toFileName(); + private void validateFileNameToId(String actualName, ComponentId id, String artifactName) { + String expectedCanonicalFileName = id.toFileName(); + String expectedAlternativeFileName = id.stringValue().replace(":", "-").replace("/", "_"); // legacy + String fileName = new File(actualName).getName(); + fileName = stripXmlEnding(fileName); + String canonicalFileName = ComponentId.fromFileName(fileName).toFileName(); if ( ! canonicalFileName.equals(expectedCanonicalFileName) && ! canonicalFileName.equals(expectedAlternativeFileName)) throw new IllegalArgumentException("The file name of " + artifactName + " '" + id + - "' must be '" + expectedCanonicalFileName + ".xml' but was '" + actualName + "'"); + "' must be '" + expectedCanonicalFileName + ".xml' but was '" + + actualName + "'"); } private String stripXmlEnding(String fileName) { - if (!fileName.endsWith(".xml")) + if ( ! fileName.endsWith(".xml")) throw new IllegalArgumentException("'" + fileName + "' should have a .xml ending"); else return fileName.substring(0,fileName.length()-4); } private String[] toArray(String csv) { - String[] array=csv.split(","); - for (int i=0; i<array.length; i++) - array[i]=array[i].trim(); + String[] array = csv.split(","); + for (int i = 0; i < array.length; i++) + array[i] = array[i].trim(); return array; } public void fillQueryProfileTypes(List<Element> queryProfileTypeElements, QueryProfileTypeRegistry registry) { for (Element element : queryProfileTypeElements) { - QueryProfileType type=registry.getComponent(new ComponentSpecification(element.getAttribute("id")).toId()); + QueryProfileType type = registry.getComponent(new ComponentSpecification(element.getAttribute("id")).toId()); try { - readInheritedTypes(element,type,registry); - readFieldDefinitions(element,type,registry); + readInheritedTypes(element, type, registry); + readFieldDefinitions(element, type, registry); } catch (RuntimeException e) { - throw new IllegalArgumentException("Error reading " + type,e); + throw new IllegalArgumentException("Error reading " + type, e); } } } - private void readInheritedTypes(Element element,QueryProfileType type,QueryProfileTypeRegistry registry) { - String inheritedString=element.getAttribute("inherits"); - if (inheritedString==null || inheritedString.equals("")) return; + private void readInheritedTypes(Element element,QueryProfileType type, QueryProfileTypeRegistry registry) { + String inheritedString = element.getAttribute("inherits"); + if (inheritedString == null || inheritedString.equals("")) return; for (String inheritedId : inheritedString.split(" ")) { - inheritedId=inheritedId.trim(); + inheritedId = inheritedId.trim(); if (inheritedId.equals("")) continue; - QueryProfileType inheritedType=registry.getComponent(inheritedId); - if (inheritedType==null) throw new IllegalArgumentException("Could not resolve inherited query profile type '" + inheritedId); + QueryProfileType inheritedType = registry.getComponent(inheritedId); + if (inheritedType == null) + throw new IllegalArgumentException("Could not resolve inherited query profile type '" + inheritedId); type.inherited().add(inheritedType); } } - private void readFieldDefinitions(Element element,QueryProfileType type,QueryProfileTypeRegistry registry) { + private void readFieldDefinitions(Element element, QueryProfileType type, QueryProfileTypeRegistry registry) { for (Element field : XML.getChildren(element,"field")) { - String name=field.getAttribute("name"); - if (name==null || name.equals("")) throw new IllegalArgumentException("A field has no 'name' attribute"); + String name = field.getAttribute("name"); + if (name == null || name.equals("")) throw new IllegalArgumentException("A field has no 'name' attribute"); try { - String fieldTypeName=field.getAttribute("type"); - if (fieldTypeName==null) throw new IllegalArgumentException("Field '" + field + "' has no 'type' attribute"); + String fieldTypeName = field.getAttribute("type"); + if (fieldTypeName == null) throw new IllegalArgumentException("Field '" + field + "' has no 'type' attribute"); FieldType fieldType=FieldType.fromString(fieldTypeName,registry); - type.addField(new FieldDescription(name,fieldType,field.getAttribute("alias"), - getBooleanAttribute("mandatory",false,field),getBooleanAttribute("overridable",true,field)), registry); + type.addField(new FieldDescription(name, + fieldType, + field.getAttribute("alias"), + getBooleanAttribute("mandatory", false, field), + getBooleanAttribute("overridable", true, field)), + registry); } catch(RuntimeException e) { throw new IllegalArgumentException("Invalid field '" + name + "'",e); @@ -229,46 +232,51 @@ public class QueryProfileXMLReader { public void fillQueryProfiles(List<Element> queryProfileElements, QueryProfileRegistry registry) { for (Element element : queryProfileElements) { // Lookup by exact id - QueryProfile profile=registry.getComponent(new ComponentSpecification(element.getAttribute("id")).toId()); + QueryProfile profile = registry.getComponent(new ComponentSpecification(element.getAttribute("id")).toId()); try { - readInherited(element,profile,registry,null,profile.toString()); - readFields(element,profile,registry,null,profile.toString()); - readVariants(element,profile,registry); + readInherited(element, profile, registry,null, profile.toString()); + readFields(element, profile, registry,null, profile.toString()); + readVariants(element, profile, registry); } catch (RuntimeException e) { - throw new IllegalArgumentException("Error reading " + profile,e); + throw new IllegalArgumentException("Error reading " + profile, e); } } } - private void readInherited(Element element,QueryProfile profile,QueryProfileRegistry registry,DimensionValues dimensionValues,String sourceDescription) { - String inheritedString=element.getAttribute("inherits"); - if (inheritedString==null || inheritedString.equals("")) return; + private void readInherited(Element element, QueryProfile profile, QueryProfileRegistry registry, + DimensionValues dimensionValues, String sourceDescription) { + String inheritedString = element.getAttribute("inherits"); + if (inheritedString == null || inheritedString.equals("")) return; for (String inheritedId : inheritedString.split(" ")) { - inheritedId=inheritedId.trim(); + inheritedId = inheritedId.trim(); if (inheritedId.equals("")) continue; - QueryProfile inheritedProfile=registry.getComponent(inheritedId); - if (inheritedProfile==null) throw new IllegalArgumentException("Could not resolve inherited query profile '" + inheritedId + "' in " + sourceDescription); + QueryProfile inheritedProfile = registry.getComponent(inheritedId); + if (inheritedProfile == null) + throw new IllegalArgumentException("Could not resolve inherited query profile '" + + inheritedId + "' in " + sourceDescription); profile.addInherited(inheritedProfile,dimensionValues); } } - private void readFields(Element element,QueryProfile profile,QueryProfileRegistry registry,DimensionValues dimensionValues,String sourceDescription) { - List<KeyValue> references=new ArrayList<>(); - List<KeyValue> properties=new ArrayList<>(); + private void readFields(Element element,QueryProfile profile, QueryProfileRegistry registry, + DimensionValues dimensionValues, String sourceDescription) { + List<KeyValue> references = new ArrayList<>(); + List<KeyValue> properties = new ArrayList<>(); for (Element field : XML.getChildren(element,"field")) { - String name=field.getAttribute("name"); - if (name==null || name.equals("")) throw new IllegalArgumentException("A field in " + sourceDescription + " has no 'name' attribute"); + String name = field.getAttribute("name"); + if (name == null || name.equals("")) + throw new IllegalArgumentException("A field in " + sourceDescription + " has no 'name' attribute"); try { - Boolean overridable=getBooleanAttribute("overridable",null,field); - if (overridable!=null) - profile.setOverridable(name,overridable,null); + Boolean overridable = getBooleanAttribute("overridable",null,field); + if (overridable != null) + profile.setOverridable(name, overridable, null); - Object fieldValue=readFieldValue(field,name,sourceDescription,registry); + Object fieldValue = readFieldValue(field, name, sourceDescription, registry); if (fieldValue instanceof QueryProfile) - references.add(new KeyValue(name,fieldValue)); + references.add(new KeyValue(name, fieldValue)); else - properties.add(new KeyValue(name,fieldValue)); + properties.add(new KeyValue(name, fieldValue)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid field '" + name + "' in " + sourceDescription,e); @@ -276,18 +284,18 @@ public class QueryProfileXMLReader { } // Must set references before properties for (KeyValue keyValue : references) - profile.set(keyValue.getKey() ,keyValue.getValue(), dimensionValues, registry); + profile.set(keyValue.getKey(), keyValue.getValue(), dimensionValues, registry); for (KeyValue keyValue : properties) profile.set(keyValue.getKey(), keyValue.getValue(), dimensionValues, registry); } - private Object readFieldValue(Element field,String name,String targetDescription,QueryProfileRegistry registry) { - Element ref=XML.getChild(field,"ref"); - if (ref!=null) { - String referencedName=XML.getValue(ref); - QueryProfile referenced=registry.getComponent(referencedName); - if (referenced==null) + private Object readFieldValue(Element field, String name, String targetDescription, QueryProfileRegistry registry) { + Element ref = XML.getChild(field,"ref"); + if (ref != null) { + String referencedName = XML.getValue(ref); + QueryProfile referenced = registry.getComponent(referencedName); + if (referenced == null) throw new IllegalArgumentException("Could not find query profile '" + referencedName + "' referenced as '" + name + "' in " + targetDescription); return referenced; @@ -297,40 +305,41 @@ public class QueryProfileXMLReader { } } - private void readVariants(Element element,QueryProfile profile,QueryProfileRegistry registry) { + private void readVariants(Element element, QueryProfile profile, QueryProfileRegistry registry) { for (Element queryProfileVariantElement : XML.getChildren(element,"query-profile")) { // A "virtual" query profile contained inside another - List<String> dimensions=profile.getDimensions(); - if (dimensions==null) + List<String> dimensions = profile.getDimensions(); + if (dimensions == null) throw new IllegalArgumentException("Cannot create a query profile variant in " + profile + ", as it has not declared any variable dimensions"); - String dimensionString=queryProfileVariantElement.getAttribute("for"); - String[] dimensionValueArray=makeStarsNull(toArray(dimensionString)); + String dimensionString = queryProfileVariantElement.getAttribute("for"); + String[] dimensionValueArray = makeStarsNull(toArray(dimensionString)); if (dimensions.size()<dimensionValueArray.length) throw new IllegalArgumentException("Cannot create a query profile variant for '" + dimensionString + "' as only " + dimensions.size() + " dimensions has been defined"); - DimensionValues dimensionValues=DimensionValues.createFrom(dimensionValueArray); + DimensionValues dimensionValues = DimensionValues.createFrom(dimensionValueArray); - String description="variant '" + dimensionString + "' in " + profile.toString(); - readInherited(queryProfileVariantElement,profile,registry,dimensionValues,description); - readFields(queryProfileVariantElement,profile,registry,dimensionValues,description); + String description = "variant '" + dimensionString + "' in " + profile.toString(); + readInherited(queryProfileVariantElement, profile, registry, dimensionValues, description); + readFields(queryProfileVariantElement, profile, registry, dimensionValues, description); } } private String[] makeStarsNull(String[] strings) { - for (int i=0; i<strings.length; i++) + for (int i = 0; i < strings.length; i++) if (strings[i].equals("*")) - strings[i]=null; + strings[i] = null; return strings; } /** - * Returns true if the string is "true".<br> - * Returns false if the string is "false".<br> - * Returns <code>default</code> if the string is null or empty (this parameter may be null)<br> + * Returns true if the string is "true". + * Returns false if the string is "false". + * Returns <code>default</code> if the string is null or empty (this parameter may be null). + * * @throws IllegalArgumentException if the string has any other value */ private Boolean asBoolean(String s,Boolean defaultValue) { - if (s==null) return defaultValue; + if (s == null) return defaultValue; if (s.isEmpty()) return defaultValue; if ("true".equals(s)) return true; if ("false".equals(s)) return false; @@ -338,12 +347,12 @@ public class QueryProfileXMLReader { } /** Returns the given attribute as a boolean, using the semantics of {@link #asBoolean} */ - private Boolean getBooleanAttribute(String attributeName,Boolean defaultValue,Element from) { + private Boolean getBooleanAttribute(String attributeName, Boolean defaultValue, Element from) { try { - return asBoolean(from.getAttribute(attributeName),defaultValue); + return asBoolean(from.getAttribute(attributeName), defaultValue); } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("Attribute '" + attributeName,e); + throw new IllegalArgumentException("Attribute '" + attributeName, e); } } @@ -352,9 +361,9 @@ public class QueryProfileXMLReader { private String key; private Object value; - public KeyValue(String key,Object value) { - this.key=key; - this.value=value; + public KeyValue(String key, Object value) { + this.key = key; + this.value = value; } public String getKey() { return key; } |