improved attribute handling in CQL->RPN conversion
This commit is contained in:
parent
c6dc31628f
commit
3226ce424b
5 changed files with 87 additions and 63 deletions
|
@ -1,5 +1,5 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = z3950
|
name = z3950
|
||||||
version = 5.1.4
|
version = 5.1.5
|
||||||
|
|
||||||
org.gradle.warning.mode = ALL
|
org.gradle.warning.mode = ALL
|
||||||
|
|
|
@ -208,7 +208,8 @@ public final class CQLRPNGenerator implements Visitor {
|
||||||
}
|
}
|
||||||
operand.attrTerm.attributes = new AttributeList();
|
operand.attrTerm.attributes = new AttributeList();
|
||||||
operand.attrTerm.attributes.value = attributeElements.stream()
|
operand.attrTerm.attributes.value = attributeElements.stream()
|
||||||
.filter(ae -> ae.attributeValue != null).toArray(AttributeElement[]::new);
|
.filter(ae -> ae.attributeValue != null)
|
||||||
|
.toArray(AttributeElement[]::new);
|
||||||
RPNStructure rpn = new RPNStructure();
|
RPNStructure rpn = new RPNStructure();
|
||||||
rpn.c_op = operand;
|
rpn.c_op = operand;
|
||||||
result.push(rpn);
|
result.push(rpn);
|
||||||
|
@ -219,37 +220,30 @@ public final class CQLRPNGenerator implements Visitor {
|
||||||
if (node.getModifierList() != null) {
|
if (node.getModifierList() != null) {
|
||||||
node.getModifierList().accept(this);
|
node.getModifierList().accept(this);
|
||||||
}
|
}
|
||||||
int attributeType = 2;
|
|
||||||
int attributeValue = 3; // EQUALS, 2=3
|
|
||||||
switch (node.getComparitor()) {
|
switch (node.getComparitor()) {
|
||||||
case LESS -> // 2=1
|
case LESS -> // 2=1
|
||||||
attributeValue = 1;
|
push(attributeElements, createAttributeElement(2, 1));
|
||||||
case LESS_EQUALS -> // 2=2
|
case LESS_EQUALS -> // 2=2
|
||||||
attributeValue = 2;
|
push(attributeElements, createAttributeElement(2, 2));
|
||||||
|
case EQUALS -> // 2=3
|
||||||
|
push(attributeElements, createAttributeElement(2, 3));
|
||||||
case GREATER_EQUALS -> // 2=4
|
case GREATER_EQUALS -> // 2=4
|
||||||
attributeValue = 4;
|
push(attributeElements, createAttributeElement(2, 4));
|
||||||
case GREATER -> // 2=5
|
case GREATER -> // 2=5
|
||||||
attributeValue = 5;
|
push(attributeElements, createAttributeElement(2, 5));
|
||||||
case NOT_EQUALS -> // 2=6
|
case NOT_EQUALS ->
|
||||||
attributeValue = 6;
|
push(attributeElements, createAttributeElement(2, 6));
|
||||||
case ALL -> { // 4=6
|
case ALL -> { // 4=6 word list
|
||||||
attributeType = 4;
|
push(attributeElements, createAttributeElement(2, 3));
|
||||||
attributeValue = 6;
|
replace(attributeElements, createAttributeElement(4, 6));
|
||||||
}
|
}
|
||||||
case ANY -> { // 4=104
|
case ANY -> { // 4=104
|
||||||
attributeType = 4;
|
push(attributeElements, createAttributeElement(2, 3));
|
||||||
attributeValue = 104;
|
replace(attributeElements, createAttributeElement(4, 104));
|
||||||
}
|
}
|
||||||
default -> {
|
default -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attributeValue != 3) {
|
|
||||||
AttributeElement ae = new AttributeElement();
|
|
||||||
ae.attributeType = new ASN1Integer(attributeType);
|
|
||||||
ae.attributeValue = new AttributeElementAttributeValue();
|
|
||||||
ae.attributeValue.numeric = new ASN1Integer(attributeValue);
|
|
||||||
result.push(ae);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -294,39 +288,34 @@ public final class CQLRPNGenerator implements Visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
int attributeType = 1; // use attribute set: bib-1 = 1
|
int attributeType = 1; // use attribute set: bib-1 = 1
|
||||||
int attributeValue = getUseAttr(context, index.getName());
|
Integer attributeValue = getUseAttr(context, index.getName());
|
||||||
|
if (attributeValue == null) {
|
||||||
|
throw new SyntaxException("undefined attribute value for " + index.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// date --> use year attribute
|
||||||
|
if (attributeValue == 31) {
|
||||||
|
replace(attributeElements, createAttributeElement(4, 5));
|
||||||
|
}
|
||||||
push(attributeElements, createAttributeElement(attributeType, attributeValue));
|
push(attributeElements, createAttributeElement(attributeType, attributeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getUseAttr(String context, String attrName) {
|
private Integer getUseAttr(String context, String attrName) {
|
||||||
if (!contexts.containsKey(context)) {
|
if (!contexts.containsKey(context)) {
|
||||||
throw new SyntaxException("unknown use attribute '" + attrName + "' for context " + context);
|
throw new SyntaxException("unknown use attribute '" + attrName + "' for context " + context);
|
||||||
}
|
}
|
||||||
return Integer.parseInt(contexts.get(context).get(attrName));
|
String string = contexts.get(context).get(attrName);
|
||||||
|
return string != null ? Integer.parseInt(string) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ASN1OctetString transformTerm(Term term) {
|
private ASN1OctetString transformTerm(Term term) {
|
||||||
|
|
||||||
int firstAttributeValue = 0;
|
|
||||||
if (!attributeElements.isEmpty()) {
|
|
||||||
AttributeElement attributeElement = attributeElements.peek();
|
|
||||||
if (attributeElement.attributeType.get() == 1) {
|
|
||||||
firstAttributeValue = attributeElement.attributeValue.numeric.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String v = term.getValue();
|
String v = term.getValue();
|
||||||
// let's derive attributes from the search term syntax
|
// let's derive basic attributes from the search term syntax
|
||||||
|
|
||||||
// relation attribute = 2
|
|
||||||
int attributeType = 2;
|
|
||||||
int attributeValue = 3; // equal 2=3
|
|
||||||
push(attributeElements, createAttributeElement(attributeType, attributeValue));
|
|
||||||
|
|
||||||
// position attribute = 3
|
// position attribute = 3
|
||||||
attributeType = 3;
|
int attributeType = 3;
|
||||||
attributeValue = 3; // any position = 3
|
int attributeValue = 3; // any position = 3
|
||||||
if (v.startsWith("^")) {
|
if (v.startsWith("^")) {
|
||||||
attributeValue = 1; // first posiiton
|
attributeValue = 1; // first posiiton
|
||||||
v = v.substring(1);
|
v = v.substring(1);
|
||||||
|
@ -335,17 +324,11 @@ public final class CQLRPNGenerator implements Visitor {
|
||||||
|
|
||||||
// structure attribute = 4
|
// structure attribute = 4
|
||||||
attributeType = 4;
|
attributeType = 4;
|
||||||
attributeValue = 2; // phrase = 1, word = 2
|
attributeValue = 2; // phrase = 1, word = 2, word list = 6
|
||||||
if (v.startsWith("\"") && v.endsWith("\"")) {
|
if (v.startsWith("\"") && v.endsWith("\"")) {
|
||||||
attributeValue = 1; // phrase
|
attributeValue = 1; // phrase
|
||||||
v = v.substring(1, v.length()-1);
|
v = v.substring(1, v.length()-1);
|
||||||
}
|
}
|
||||||
if (firstAttributeValue == 31) {
|
|
||||||
attributeValue = 5; // date (normalized) = 5
|
|
||||||
}
|
|
||||||
if (firstAttributeValue == 1016) {
|
|
||||||
attributeValue = 6; // word list
|
|
||||||
}
|
|
||||||
push(attributeElements, createAttributeElement(attributeType, attributeValue));
|
push(attributeElements, createAttributeElement(attributeType, attributeValue));
|
||||||
|
|
||||||
// truncation attribute = 5
|
// truncation attribute = 5
|
||||||
|
@ -377,14 +360,6 @@ public final class CQLRPNGenerator implements Visitor {
|
||||||
return new ASN1OctetString(v);
|
return new ASN1OctetString(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void push(Stack<AttributeElement> stack, AttributeElement attributeElement) {
|
|
||||||
if (attributeElement != null) {
|
|
||||||
if (!stack.contains(attributeElement)) {
|
|
||||||
stack.push(attributeElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AttributeElement createAttributeElement(Integer attributeType, Integer attributeValue) {
|
private static AttributeElement createAttributeElement(Integer attributeType, Integer attributeValue) {
|
||||||
if (attributeType != null && attributeValue != null) {
|
if (attributeType != null && attributeValue != null) {
|
||||||
AttributeElement ae = new AttributeElement();
|
AttributeElement ae = new AttributeElement();
|
||||||
|
@ -396,4 +371,21 @@ public final class CQLRPNGenerator implements Visitor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void push(Stack<AttributeElement> stack, AttributeElement attributeElement) {
|
||||||
|
if (attributeElement != null) {
|
||||||
|
stack.push(attributeElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void replace(Stack<AttributeElement> stack, AttributeElement attributeElement) {
|
||||||
|
if (attributeElement != null) {
|
||||||
|
int pos = stack.indexOf(attributeElement);
|
||||||
|
if (pos >= 0) {
|
||||||
|
stack.remove(pos);
|
||||||
|
}
|
||||||
|
stack.push(attributeElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,4 +164,14 @@ public final class AttributeElement extends ASN1Any implements Comparable<Attrib
|
||||||
public int compareTo(AttributeElement o) {
|
public int compareTo(AttributeElement o) {
|
||||||
return attributeType.toString().compareTo(o.attributeType.toString());
|
return attributeType.toString().compareTo(o.attributeType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return attributeType.toString().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof AttributeElement && attributeType.toString().equals(((AttributeElement) obj).attributeType.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ dateAcquisition=32
|
||||||
dateComposition=1196
|
dateComposition=1196
|
||||||
dateConference=1054
|
dateConference=1054
|
||||||
datePublication=31
|
datePublication=31
|
||||||
|
datePublished=31
|
||||||
dateRecordStatus=1055
|
dateRecordStatus=1055
|
||||||
dateRecording=1197
|
dateRecording=1197
|
||||||
dateTimeAddedDB=1011
|
dateTimeAddedDB=1011
|
||||||
|
|
|
@ -18,7 +18,7 @@ class CQL2RPNTest {
|
||||||
CQLRPNGenerator generator = new CQLRPNGenerator();
|
CQLRPNGenerator generator = new CQLRPNGenerator();
|
||||||
parser.getCQLQuery().accept(generator);
|
parser.getCQLQuery().accept(generator);
|
||||||
String q = generator.getQueryResult().toString();
|
String q = generator.getQueryResult().toString();
|
||||||
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 2, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 2}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"Test\"}}}}}", q);
|
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 3, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 2}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 1, attributeValue {numeric 4}}{attributeType 2, attributeValue {numeric 3}}}, term {general \"Test\"}}}}}", q);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -29,13 +29,13 @@ class CQL2RPNTest {
|
||||||
CQLRPNGenerator generator = new CQLRPNGenerator();
|
CQLRPNGenerator generator = new CQLRPNGenerator();
|
||||||
parser.getCQLQuery().accept(generator);
|
parser.getCQLQuery().accept(generator);
|
||||||
String q = generator.getQueryResult().toString();
|
String q = generator.getQueryResult().toString();
|
||||||
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 2, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 1}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"a phrase\"}}}}}", q);
|
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 3, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 1}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 1, attributeValue {numeric 4}}{attributeType 2, attributeValue {numeric 3}}}, term {general \"a phrase\"}}}}}", q);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithOverridingAnAttribute() {
|
void testWithCustomAttribute() {
|
||||||
AttributeElement ae = new AttributeElement();
|
AttributeElement ae = new AttributeElement();
|
||||||
ae.attributeType = new ASN1Integer(2);
|
ae.attributeType = new ASN1Integer(7);
|
||||||
ae.attributeValue = new AttributeElementAttributeValue();
|
ae.attributeValue = new AttributeElementAttributeValue();
|
||||||
ae.attributeValue.numeric = new ASN1Integer(4);
|
ae.attributeValue.numeric = new ASN1Integer(4);
|
||||||
String cql = "dc.title = \"a phrase\"";
|
String cql = "dc.title = \"a phrase\"";
|
||||||
|
@ -44,8 +44,7 @@ class CQL2RPNTest {
|
||||||
CQLRPNGenerator generator = new CQLRPNGenerator(Collections.singleton(ae));
|
CQLRPNGenerator generator = new CQLRPNGenerator(Collections.singleton(ae));
|
||||||
parser.getCQLQuery().accept(generator);
|
parser.getCQLQuery().accept(generator);
|
||||||
String q = generator.getQueryResult().toString();
|
String q = generator.getQueryResult().toString();
|
||||||
// not really working, it adds, not override
|
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 7, attributeValue {numeric 4}}{attributeType 3, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 1}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 1, attributeValue {numeric 4}}{attributeType 2, attributeValue {numeric 3}}}, term {general \"a phrase\"}}}}}", q);
|
||||||
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 2, attributeValue {numeric 4}}{attributeType 2, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 1}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"a phrase\"}}}}}", q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -56,6 +55,28 @@ class CQL2RPNTest {
|
||||||
CQLRPNGenerator generator = new CQLRPNGenerator();
|
CQLRPNGenerator generator = new CQLRPNGenerator();
|
||||||
parser.getCQLQuery().accept(generator);
|
parser.getCQLQuery().accept(generator);
|
||||||
String q = generator.getQueryResult().toString();
|
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 2}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 1, attributeValue {numeric 12}}}, term {general \"123\"}}}}}", q);
|
assertEquals("{attributeSetId 1.2.840.10003.3.1, rpn {op {attrTerm {attributes {{attributeType 3, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 2}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 1, attributeValue {numeric 12}}{attributeType 2, attributeValue {numeric 3}}}, term {general \"123\"}}}}}", q);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAll() {
|
||||||
|
String cql = "bib.any all \"zeitschrift umweltrecht\"";
|
||||||
|
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 3, attributeValue {numeric 3}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 1, attributeValue {numeric 1016}}{attributeType 2, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 6}}}, term {general \"zeitschrift umweltrecht\"}}}}}", q);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDate() {
|
||||||
|
String cql = "bib.datePublication = 2023";
|
||||||
|
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 3, attributeValue {numeric 3}}{attributeType 5, attributeValue {numeric 100}}{attributeType 6, attributeValue {numeric 1}}{attributeType 4, attributeValue {numeric 5}}{attributeType 1, attributeValue {numeric 31}}{attributeType 2, attributeValue {numeric 3}}}, term {general \"2023\"}}}}}", q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue