update netty to 4.1.51, xbib cql to 3.0.2, fix attribute list deriving from CQL search term

This commit is contained in:
Jörg Prante 2020-07-31 10:57:20 +02:00
parent d14cfe0e08
commit 39a962cbdf
8 changed files with 133 additions and 98 deletions

View file

@ -1,8 +1,8 @@
group = org.xbib
name = z3950
version = 2.2.0
version = 2.2.1
gradle.wrapper.version = 6.4.1
netty.version = 4.1.50.Final
xbib-cql.version = 3.0.1
netty.version = 4.1.51.Final
xbib-cql.version = 3.0.2
xbib-bibliographic-character-sets.version = 2.0.0

View file

@ -32,7 +32,6 @@ import org.xbib.z3950.common.v3.Operator;
import org.xbib.z3950.common.v3.RPNQuery;
import org.xbib.z3950.common.v3.RPNStructure;
import org.xbib.z3950.common.v3.RPNStructureRpnRpnOp;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
@ -49,18 +48,25 @@ public final class CQLRPNGenerator implements Visitor {
/**
* Context map.
*/
private final Map<String, ResourceBundle> contexts = new HashMap<String, ResourceBundle>() {
private final Map<String, ResourceBundle> contexts = new HashMap<>() {
private static final long serialVersionUID = 8199395368653216950L;
{
put("cql", ResourceBundle.getBundle("org.xbib.z3950.common.cql.cql"));
put("bib", ResourceBundle.getBundle("org.xbib.z3950.common.cql.bib-1"));
put("dc", ResourceBundle.getBundle("org.xbib.z3950.common.cql.dc"));
put("gbv", ResourceBundle.getBundle("org.xbib.z3950.common.cql.gbv"));
put("dc", ResourceBundle.getBundle("org.xbib.z3950.common.cql.dc"));
put("gbv", ResourceBundle.getBundle("org.xbib.z3950.common.cql.gbv"));
}
};
private Stack<ASN1Any> result;
private final Stack<AttributeElement> attributeElements;
private final Stack<ASN1Any> result;
private RPNQuery rpnQuery;
public CQLRPNGenerator() {
this.attributeElements = new Stack<>();
this.result = new Stack<>();
}
@ -80,8 +86,8 @@ public final class CQLRPNGenerator implements Visitor {
this.rpnQuery = new RPNQuery();
rpnQuery.rpn = (RPNStructure) result.pop();
// Z39.50 BIB-1: urn:oid:1.2.840.10003.3.1
rpnQuery.attributeSet = new AttributeSetId();
rpnQuery.attributeSet.value = new ASN1ObjectIdentifier(new int[]{1, 2, 840, 10003, 3, 1});
rpnQuery.attributeSetId = new AttributeSetId();
rpnQuery.attributeSetId.value = new ASN1ObjectIdentifier(new int[]{1, 2, 840, 10003, 3, 1});
} else {
throw new SyntaxException("unable to generate RPN from CQL");
}
@ -183,15 +189,14 @@ public final class CQLRPNGenerator implements Visitor {
Operand operand = new Operand();
operand.attrTerm = new AttributesPlusTerm();
operand.attrTerm.term = new org.xbib.z3950.common.v3.Term();
operand.attrTerm.term.c_general = new ASN1OctetString(node.getTerm().getValue());
Stack<AttributeElement> attrs = new Stack<>();
ASN1Any any = !result.isEmpty() && result.peek() instanceof AttributeElement ? result.pop() : null;
while (any != null) {
attrs.push((AttributeElement) any);
any = !result.isEmpty() && result.peek() instanceof AttributeElement ? result.pop() : null;
ASN1Any any = result.pop();
if (any instanceof ASN1OctetString) {
operand.attrTerm.term.c_general = (ASN1OctetString)any;
} else {
operand.attrTerm.term.c_general = new ASN1OctetString(node.getTerm().getValue());
}
operand.attrTerm.attributes = new AttributeList();
operand.attrTerm.attributes.value = attrs.toArray(new AttributeElement[attrs.size()]);
operand.attrTerm.attributes.value = attributeElements.toArray(new AttributeElement[0]);
RPNStructure rpn = new RPNStructure();
rpn.c_op = operand;
result.push(rpn);
@ -202,43 +207,43 @@ public final class CQLRPNGenerator implements Visitor {
if (node.getModifierList() != null) {
node.getModifierList().accept(this);
}
int t = 2;
int n = 3;
int attributeType = 2;
int attributeValue = 3;
switch (node.getComparitor()) {
case LESS: // 2=1
n = 1;
attributeValue = 1;
break;
case LESS_EQUALS: // 2=2
n = 2;
attributeValue = 2;
break;
case EQUALS: // 2=3
n = 3;
attributeValue = 3;
break;
case GREATER_EQUALS: // 2=4
n = 4;
attributeValue = 4;
break;
case GREATER: // 2=5
n = 5;
attributeValue = 5;
break;
case NOT_EQUALS: // 2=6
n = 6;
attributeValue = 6;
break;
case ALL: // 4=6
t = 4;
n = 6;
attributeType = 4;
attributeValue = 6;
break;
case ANY: // 4=105
t = 4;
n = 104;
attributeType = 4;
attributeValue = 104;
break;
default:
break;
}
if (n != 3) {
if (attributeValue != 3) {
AttributeElement ae = new AttributeElement();
ae.attributeType = new ASN1Integer(t);
ae.attributeType = new ASN1Integer(attributeType);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(n);
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
result.push(ae);
}
}
@ -261,29 +266,9 @@ public final class CQLRPNGenerator implements Visitor {
}
@Override
public void visit(Term node) {
int t = 5;
int n = 100;
// check for '*'
String v = node.getValue();
if (v.endsWith("*")) {
if (v.startsWith("*")) {
n = 3;
} else {
n = 1;
}
} else if (v.startsWith("*")) {
n = 2;
}
if (n != 100) {
AttributeElement ae = new AttributeElement();
ae.attributeType = new ASN1Integer(t);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(n);
result.push(ae);
v = v.replaceAll("\\*", "");
}
ASN1OctetString s = new ASN1OctetString(v);
public void visit(Term term) {
// the value
ASN1OctetString s = transformTerm(term);
result.push(s);
}
@ -298,18 +283,18 @@ public final class CQLRPNGenerator implements Visitor {
}
@Override
public void visit(Index node) {
String context = node.getContext();
public void visit(Index index) {
String context = index.getContext();
if (context == null) {
context = "dc"; // default context
}
int t = 1;
int n = getUseAttr(context, node.getName());
int attributeType = 1; // use attribute set: bib-1 = 1
int attributeValue = getUseAttr(context, index.getName());
AttributeElement ae = new AttributeElement();
ae.attributeType = new ASN1Integer(t);
ae.attributeType = new ASN1Integer(attributeType);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(n);
result.push(ae);
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
attributeElements.push(ae);
}
private int getUseAttr(String context, String attrName) {
@ -319,4 +304,63 @@ public final class CQLRPNGenerator implements Visitor {
throw new SyntaxException("unknown use attribute '" + attrName + "' for context " + context, e);
}
}
private ASN1OctetString transformTerm(Term term) {
String v = term.getValue();
// let's derive attributes from the search term
// relation attribute = 2
int attributeType = 2;
int attributeValue = 3; // equal = 3
AttributeElement ae = new AttributeElement();
ae.attributeType = new ASN1Integer(attributeType);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
attributeElements.push(ae);
// position attribute = 3
attributeType = 3;
attributeValue = 3; // any position = 3
ae = new AttributeElement();
ae.attributeType = new ASN1Integer(attributeType);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
attributeElements.push(ae);
// structure attribute = 4
attributeType = 4;
attributeValue = 2; // word = 2
if (v.startsWith("\"") && v.endsWith("\"")) {
attributeValue = 1; // phrase
v = v.substring(1, v.length()-1);
}
ae = new AttributeElement();
ae.attributeType = new ASN1Integer(attributeType);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
attributeElements.push(ae);
// truncation attribute = 5
attributeType = 5;
attributeValue = 100; // do not truncate = 5
if (v.endsWith("*")) {
if (v.startsWith("*")) {
attributeValue = 3; // Left and right truncation = 3
v = v.substring(1, v.length() - 1);
} else {
attributeValue = 1; // Right truncation = 1
v = v.substring(0, v.length() - 1);
}
} else if (v.startsWith("*")) {
attributeValue = 2; // Left truncation = 2
v = v.substring(1);
}
ae = new AttributeElement();
ae.attributeType = new ASN1Integer(attributeType);
ae.attributeValue = new AttributeElementAttributeValue();
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
attributeElements.push(ae);
return new ASN1OctetString(v);
}
}

View file

@ -42,8 +42,8 @@ public class PQFRPNGenerator implements Visitor {
rpnQuery.rpn = (RPNStructure) result.pop();
if (pqf.getAttrSet() == null) {
// Z39.50 BIB-1: urn:oid:1.2.840.10003.3.1
rpnQuery.attributeSet = new AttributeSetId();
rpnQuery.attributeSet.value = new ASN1ObjectIdentifier(new int[]{1, 2, 840, 10003, 3, 1});
rpnQuery.attributeSetId = new AttributeSetId();
rpnQuery.attributeSetId.value = new ASN1ObjectIdentifier(new int[]{1, 2, 840, 10003, 3, 1});
}
} else {
throw new SyntaxException("no valid PQF found");

View file

@ -89,7 +89,7 @@ public final class AttributeList extends ASN1Any {
*/
@Override
public BEREncoding berEncode(int tagType, int tag) throws ASN1Exception {
BEREncoding fields[] = new BERConstructed[value.length];
BEREncoding[] fields = new BERConstructed[value.length];
int p;
for (p = 0; p < value.length; p++) {
fields[p] = value[p].berEncode();

View file

@ -19,7 +19,9 @@ import org.xbib.asn1.BEREncoding;
public final class Operand extends ASN1Any {
public AttributesPlusTerm attrTerm;
public ResultSetId resultSet;
public ResultSetPlusAttributes resultAttr;
public Operand() {
@ -50,11 +52,9 @@ public final class Operand extends ASN1Any {
@Override
public void berDecode(BEREncoding ber, boolean checkTag) throws ASN1Exception {
// Null out all choices
attrTerm = null;
resultSet = null;
resultAttr = null;
// Try choice attrTerm
try {
attrTerm = new AttributesPlusTerm(ber, checkTag);
@ -62,7 +62,6 @@ public final class Operand extends ASN1Any {
} catch (ASN1Exception e) {
// failed to decode, continue on
}
// Try choice resultSet
try {
resultSet = new ResultSetId(ber, checkTag);
@ -70,7 +69,6 @@ public final class Operand extends ASN1Any {
} catch (ASN1Exception e) {
// failed to decode, continue on
}
// Try choice resultAttr
try {
resultAttr = new ResultSetPlusAttributes(ber, checkTag);
@ -78,7 +76,6 @@ public final class Operand extends ASN1Any {
} catch (ASN1Exception e) {
// failed to decode, continue on
}
throw new ASN1Exception("bad BER encoding: choice not matched");
}
@ -91,12 +88,10 @@ public final class Operand extends ASN1Any {
@Override
public BEREncoding berEncode() throws ASN1Exception {
BEREncoding chosen = null;
// Encoding choice: c_attrTerm
if (attrTerm != null) {
chosen = attrTerm.berEncode();
}
// Encoding choice: c_resultSet
if (resultSet != null) {
if (chosen != null) {

View file

@ -19,7 +19,8 @@ import org.xbib.asn1.BEREncoding;
*/
public final class RPNQuery extends ASN1Any {
public AttributeSetId attributeSet;
public AttributeSetId attributeSetId;
public RPNStructure rpn;
/**
@ -65,7 +66,7 @@ public final class RPNQuery extends ASN1Any {
throw new ASN1Exception("incomplete");
}
p = berConstructed.elementAt(part);
attributeSet = new AttributeSetId(p, true);
attributeSetId = new AttributeSetId(p, true);
part++;
if (numParts <= part) {
throw new ASN1Exception("incomplete");
@ -100,9 +101,9 @@ public final class RPNQuery extends ASN1Any {
@Override
public BEREncoding berEncode(int tagType, int tag) throws ASN1Exception {
int numFields = 2;
BEREncoding fields[] = new BEREncoding[numFields];
BEREncoding[] fields = new BEREncoding[numFields];
int x = 0;
fields[x++] = attributeSet.berEncode();
fields[x++] = attributeSetId.berEncode();
fields[x] = rpn.berEncode();
return new BERConstructed(tagType, tag, fields);
}
@ -113,17 +114,6 @@ public final class RPNQuery extends ASN1Any {
*/
@Override
public String toString() {
StringBuilder str = new StringBuilder("{");
int outputted = 0;
str.append("attributeSet ");
str.append(attributeSet);
outputted++;
if (0 < outputted) {
str.append(", ");
}
str.append("rpn ");
str.append(rpn);
str.append("}");
return str.toString();
return "{" + "attributeSetId " + attributeSetId + ", " + "rpn " + rpn + "}";
}
}

View file

@ -19,6 +19,7 @@ import org.xbib.asn1.BEREncoding;
public final class RPNStructure extends ASN1Any {
public Operand c_op;
public RPNStructureRpnRpnOp c_rpnRpnOp;
/**
@ -86,16 +87,13 @@ public final class RPNStructure extends ASN1Any {
@Override
public BEREncoding berEncode() throws ASN1Exception {
BEREncoding chosen = null;
BEREncoding enc[];
BEREncoding[] enc;
// Encoding choice: c_op
if (c_op != null) {
enc = new BEREncoding[1];
enc[0] = c_op.berEncode();
chosen = new BERConstructed(BEREncoding.CONTEXT_SPECIFIC_TAG, 0, enc);
}
// Encoding choice: c_rpnRpnOp
if (c_rpnRpnOp != null) {
if (chosen != null) {
@ -103,7 +101,6 @@ public final class RPNStructure extends ASN1Any {
}
chosen = c_rpnRpnOp.berEncode(BEREncoding.CONTEXT_SPECIFIC_TAG, 1);
}
// Check for error of having none of the choices set
if (chosen == null) {
throw new ASN1Exception("CHOICE not set");

View file

@ -1,21 +1,30 @@
package org.xbib.z3950.common.cql;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.xbib.cql.CQLParser;
/**
*
*/
class CQL2RPNTest {
@Test
void testCQL2RPN() {
void testDublinCoreContext() {
String cql = "dc.title = Test";
CQLParser parser = new CQLParser(cql);
parser.parse();
CQLRPNGenerator generator = new CQLRPNGenerator();
parser.getCQLQuery().accept(generator);
String q = generator.getQueryResult().toString();
System.err.println("cql2rpn = " + q);
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 2, attributeValue {numeric 3}}{attributeType 3, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 2}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"Test\"}}}}}", q);
}
@Test
void testPhrase() {
String cql = "dc.title = \"a phrase\"";
CQLParser parser = new CQLParser(cql);
parser.parse();
CQLRPNGenerator generator = new CQLRPNGenerator();
parser.getCQLQuery().accept(generator);
String q = generator.getQueryResult().toString();
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 2, attributeValue {numeric 3}}{attributeType 3, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 1}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"a phrase\"}}}}}", q);
}
}