diff --git a/etc/pqf.properties b/etc/pqf.properties index 2448482..36a0483 100644 --- a/etc/pqf.properties +++ b/etc/pqf.properties @@ -96,6 +96,17 @@ structure.any = 4=2 structure.* = 4=1 # phrase +# Truncation attributes used to implement CQL wildcard patterns. The +# simpler forms, left, right- and both-truncation will be used for the +# simplest patterns, so that we produce PQF queries that conform more +# closely to the Bath Profile. However, when a more complex pattern +# such as "foo*bar" is used, we fall back on Z39.58-style masking. +# +truncation.right = 5=1 +truncation.left = 5=2 +truncation.both = 5=3 +truncation.none = 5=100 + # Finally, any additional attributes that should always be included # with each term can be specified in the "always" property. # diff --git a/src/main/java/org/z3950/zing/cql/CQLTermNode.java b/src/main/java/org/z3950/zing/cql/CQLTermNode.java index 2ad9188..a810a79 100644 --- a/src/main/java/org/z3950/zing/cql/CQLTermNode.java +++ b/src/main/java/org/z3950/zing/cql/CQLTermNode.java @@ -135,11 +135,19 @@ private List getAttrs(Properties config) throws PQFTranslationException } String pos = "any"; + String truncation = "none"; String text = term; if (text.length() > 0 && text.substring(0, 1).equals("^")) { text = text.substring(1); // ### change not seen by caller pos = "first"; } + if (text.startsWith("*") && text.endsWith("*")) { + truncation = "both"; + } else if (text.startsWith("*")) { + truncation = "left"; + } else if (text.endsWith("*")) { + truncation = "right"; + } int len = text.length(); if (len > 0 && text.substring(len-1, len).equals("^")) { text = text.substring(0, len-1); // ### change not seen by caller @@ -156,6 +164,11 @@ private List getAttrs(Properties config) throws PQFTranslationException throw new UnknownPositionException(pos); attrs.add(attr); + attr = config.getProperty("truncation." + truncation); + if (attr == null) + throw new UnknownTruncationException(truncation); + attrs.add(attr); + attr = config.getProperty("structure." + rel); if (attr == null) attr = config.getProperty("structure.*"); @@ -187,6 +200,15 @@ public String toPQF(Properties config) throws PQFTranslationException { if (len > 0 && text.substring(len-1, len).equals("^")) text = text.substring(0, len-1); + len = text.length(); + if (text.startsWith("*") && text.endsWith("*")) { + text = text.substring(1, len-1); + } else if (text.startsWith("*")) { + text = text.substring(1); + } else if (text.endsWith("*")) { + text = text.substring(0, len-1); + } + return s + maybeQuote(text); } diff --git a/src/main/java/org/z3950/zing/cql/UnknownTruncationException.java b/src/main/java/org/z3950/zing/cql/UnknownTruncationException.java new file mode 100644 index 0000000..3842e23 --- /dev/null +++ b/src/main/java/org/z3950/zing/cql/UnknownTruncationException.java @@ -0,0 +1,25 @@ +package org.z3950.zing.cql; + +/** + * Exception indicating that a truncation was not recognised. When rendering a + * tree out as PQF, each term is classified either as left, + * right, left and right truncated, depending on whether + * it begins and/or ends with the character *. Its + * classification is looked up as a truncation in the PQF + * configuration. If the truncation is not configured, we throw one of these + * babies. + * + */ +public class UnknownTruncationException extends PQFTranslationException { + private static final long serialVersionUID = 6971993723734811253L; + + /** + * Creates a new UnknownTruncationException. + * + * @param s + * The truncation for which there was no PQF configuration. + */ + public UnknownTruncationException(String s) { + super(s); + } +}