diff --git a/settings.gradle b/settings.gradle index 068c629..d56e284 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ include 'z3950-asn1' include 'z3950-api' include 'z3950-common' -include 'z3950-client' +include 'z3950-client-api' +include 'z3950-client-jdk' include 'z3950-client-netty' include 'z3950-sru' diff --git a/z3950-client-api/build.gradle b/z3950-client-api/build.gradle new file mode 100644 index 0000000..24032dd --- /dev/null +++ b/z3950-client-api/build.gradle @@ -0,0 +1,3 @@ +dependencies { + api project(':z3950-common') +} \ No newline at end of file diff --git a/z3950-client-api/src/main/java/module-info.java b/z3950-client-api/src/main/java/module-info.java new file mode 100644 index 0000000..df3695d --- /dev/null +++ b/z3950-client-api/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module org.xbib.z3950lib.client.api { + exports org.xbib.z3950.client.api; + requires transitive org.xbib.z3950lib.common; +} diff --git a/z3950-api/src/main/java/org/xbib/z3950/api/Client.java b/z3950-client-api/src/main/java/org/xbib/z3950/client/api/Client.java similarity index 74% rename from z3950-api/src/main/java/org/xbib/z3950/api/Client.java rename to z3950-client-api/src/main/java/org/xbib/z3950/client/api/Client.java index b5cc15d..cc67c00 100644 --- a/z3950-api/src/main/java/org/xbib/z3950/api/Client.java +++ b/z3950-client-api/src/main/java/org/xbib/z3950/client/api/Client.java @@ -1,5 +1,8 @@ -package org.xbib.z3950.api; +package org.xbib.z3950.client.api; +import org.xbib.z3950.api.RecordListener; +import org.xbib.z3950.api.ScanListener; +import org.xbib.z3950.api.SearchListener; import java.io.Closeable; import java.io.IOException; import java.util.List; @@ -7,8 +10,8 @@ import java.util.List; public interface Client extends Closeable { int searchCQL(String query, int offset, int length, - SearchListener searchListener, - RecordListener recordListener) throws IOException; + SearchListener searchListener, + RecordListener recordListener) throws IOException; int searchPQF(String query, int offset, int length, SearchListener searchListener, @@ -40,5 +43,4 @@ public interface Client extends Closeable { String getType(); List getDatabases(); - } diff --git a/z3950-api/src/main/java/org/xbib/z3950/api/ClientProvider.java b/z3950-client-api/src/main/java/org/xbib/z3950/client/api/ClientProvider.java similarity index 80% rename from z3950-api/src/main/java/org/xbib/z3950/api/ClientProvider.java rename to z3950-client-api/src/main/java/org/xbib/z3950/client/api/ClientProvider.java index 79985e0..a35e5b1 100644 --- a/z3950-api/src/main/java/org/xbib/z3950/api/ClientProvider.java +++ b/z3950-client-api/src/main/java/org/xbib/z3950/client/api/ClientProvider.java @@ -1,4 +1,4 @@ -package org.xbib.z3950.api; +package org.xbib.z3950.client.api; /** * Client provider. diff --git a/z3950-client/build.gradle b/z3950-client-jdk/build.gradle similarity index 78% rename from z3950-client/build.gradle rename to z3950-client-jdk/build.gradle index 3c6ea70..57dca3c 100644 --- a/z3950-client/build.gradle +++ b/z3950-client-jdk/build.gradle @@ -1,4 +1,4 @@ dependencies { - api project(':z3950-common') + api project(':z3950-client-api') testImplementation "org.xbib:bibliographic-character-sets:${project.property('xbib-bibliographic-character-sets.version')}" -} \ No newline at end of file +} diff --git a/z3950-client-jdk/src/main/java/module-info.java b/z3950-client-jdk/src/main/java/module-info.java new file mode 100644 index 0000000..a74e5aa --- /dev/null +++ b/z3950-client-jdk/src/main/java/module-info.java @@ -0,0 +1,5 @@ +module org.xbib.z3950lib.client.jdk { + exports org.xbib.z3950.client.jdk; + requires transitive org.xbib.z3950lib.client.api; + requires java.logging; +} \ No newline at end of file diff --git a/z3950-client/src/main/java/org/xbib/z3950/client/DefaultClient.java b/z3950-client-jdk/src/main/java/org/xbib/z3950/client/jdk/JDKZClient.java similarity index 80% rename from z3950-client/src/main/java/org/xbib/z3950/client/DefaultClient.java rename to z3950-client-jdk/src/main/java/org/xbib/z3950/client/jdk/JDKZClient.java index c7f45ff..4db0f2a 100644 --- a/z3950-client/src/main/java/org/xbib/z3950/client/DefaultClient.java +++ b/z3950-client-jdk/src/main/java/org/xbib/z3950/client/jdk/JDKZClient.java @@ -1,4 +1,4 @@ -package org.xbib.z3950.client; +package org.xbib.z3950.client.jdk; import org.xbib.asn1.io.InputStreamBERReader; import org.xbib.asn1.io.OutputStreamBERWriter; @@ -7,14 +7,14 @@ import org.xbib.z3950.common.operations.InitOperation; import org.xbib.z3950.common.operations.PresentOperation; import org.xbib.z3950.common.operations.ScanOperation; import org.xbib.z3950.common.operations.SearchOperation; -import org.xbib.z3950.api.Client; +import org.xbib.z3950.client.api.Client; import org.xbib.z3950.api.InitListener; import org.xbib.z3950.api.RecordListener; import org.xbib.z3950.api.ScanListener; import org.xbib.z3950.api.SearchListener; - import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -32,9 +32,9 @@ import java.util.logging.Logger; /** * Default Z client. */ -public class DefaultClient implements Client { +public class JDKZClient implements Client, Closeable { - private static final Logger logger = Logger.getLogger(DefaultClient.class.getName()); + private static final Logger logger = Logger.getLogger(JDKZClient.class.getName()); private final String host; @@ -72,16 +72,16 @@ public class DefaultClient implements Client { private OutputStreamBERWriter berWriter; - private DefaultClient(String host, int port, String user, String pass, long timeout, - String preferredRecordSyntax, - String resultSetName, - String elementSetName, - String encoding, - String format, - String type, - List databases, - Integer preferredMessageSize, - InitListener initListener) { + private JDKZClient(String host, int port, String user, String pass, long timeout, + String preferredRecordSyntax, + String resultSetName, + String elementSetName, + String encoding, + String format, + String type, + List databases, + Integer preferredMessageSize, + InitListener initListener) { this.host = host; this.port = port; this.user = user; @@ -99,39 +99,6 @@ public class DefaultClient implements Client { this.lock = new ReentrantLock(); } - @Override - public void close() { - if (isConnected()) { - try { - lock.lock(); - try { - sendClose(0); - } catch (IOException e) { - logger.log(Level.WARNING, "while attempting to send close for close connection: " + e.getMessage(), e); - } - try { - berReader.close(); - } catch (IOException e) { - logger.log(Level.WARNING, "error attempting to close src: " + e.getMessage(), e); - } - try { - berWriter.close(); - } catch (IOException e) { - logger.log(Level.WARNING, "error attempting to close dest: " + e.getMessage(), e); - } - try { - if (socket != null) { - socket.close(); - } - } catch (IOException e) { - logger.log(Level.WARNING, "error attempting to close socket: " + e.getMessage(), e); - } - } finally { - lock.unlock(); - } - } - } - @Override public int searchCQL(String query, int offset, int length, SearchListener searchListener, @@ -288,8 +255,66 @@ public class DefaultClient implements Client { return databases; } - private void connect() throws IOException { + public void connect() throws IOException { + try { + lock.lock(); + Socket socket = new Socket(); + socket.connect(new InetSocketAddress(host, port), (int) timeout); + socket.setSoTimeout((int) timeout * 1000); + this.socket = socket; + InputStream src = new BufferedInputStream(socket.getInputStream()); + OutputStream dest = new BufferedOutputStream(socket.getOutputStream()); + this.berReader = new InputStreamBERReader(src); + this.berWriter = new OutputStreamBERWriter(dest); + InitOperation initOperation = new InitOperation(berReader, berWriter, user, pass); + if (initOperation.execute(preferredMessageSize, initListener)) { + throw new IOException("could not initiate connection"); + } + logger.log(Level.INFO, initOperation.getTargetInfo()); + } finally { + lock.unlock(); + } + } + public void disconnect() throws IOException { + try { + lock.lock(); + try { + sendClose(0); + } catch (IOException e) { + logger.log(Level.WARNING, "while attempting to send close for close connection: " + e.getMessage(), e); + } + try { + berReader.close(); + } catch (IOException e) { + logger.log(Level.WARNING, "error attempting to close src: " + e.getMessage(), e); + } + try { + berWriter.close(); + } catch (IOException e) { + logger.log(Level.WARNING, "error attempting to close dest: " + e.getMessage(), e); + } + try { + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + logger.log(Level.WARNING, "error attempting to close socket: " + e.getMessage(), e); + } + } finally { + lock.unlock(); + } + } + + @Override + public void close() throws IOException { + if (isConnected()) { + disconnect(); + } + } + + public static Builder builder() { + return new Builder(); } private boolean isConnected() { @@ -298,31 +323,10 @@ public class DefaultClient implements Client { private void ensureConnected() throws IOException { if (!isConnected()) { - try { - lock.lock(); - Socket socket = new Socket(); - socket.connect(new InetSocketAddress(host, port), (int) timeout); - socket.setSoTimeout((int) timeout * 1000); - this.socket = socket; - InputStream src = new BufferedInputStream(socket.getInputStream()); - OutputStream dest = new BufferedOutputStream(socket.getOutputStream()); - this.berReader = new InputStreamBERReader(src); - this.berWriter = new OutputStreamBERWriter(dest); - InitOperation initOperation = new InitOperation(berReader, berWriter, user, pass); - if (initOperation.execute(preferredMessageSize, initListener)) { - throw new IOException("could not initiate connection"); - } - logger.log(Level.INFO, initOperation.getTargetInfo()); - } finally { - lock.unlock(); - } + connect(); } } - public static Builder builder() { - return new Builder(); - } - /** * Send a close request to the server. * @@ -454,8 +458,8 @@ public class DefaultClient implements Client { return this; } - public DefaultClient build() { - return new DefaultClient(host, port, user, pass, timeout, + public JDKZClient build() { + return new JDKZClient(host, port, user, pass, timeout, preferredRecordSyntax, resultSetName, elementSetName, diff --git a/z3950-client/src/test/java/org/xbib/z3950/client/test/DefaultClientTest.java b/z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/DefaultClientTest.java similarity index 90% rename from z3950-client/src/test/java/org/xbib/z3950/client/test/DefaultClientTest.java rename to z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/DefaultClientTest.java index f43e986..759f7e1 100644 --- a/z3950-client/src/test/java/org/xbib/z3950/client/test/DefaultClientTest.java +++ b/z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/DefaultClientTest.java @@ -1,7 +1,7 @@ -package org.xbib.z3950.client.test; +package org.xbib.z3950.client.jdk.test; import org.junit.jupiter.api.Test; -import org.xbib.z3950.client.DefaultClient; +import org.xbib.z3950.client.jdk.JDKZClient; import java.io.IOException; import java.io.InputStream; @@ -25,7 +25,7 @@ class DefaultClientTest { String query = "bib.identifierISSN = 00280836"; int from = 1; int size = 10; - try (DefaultClient client = newZClient(serviceName)) { + try (JDKZClient client = newZClient(serviceName)) { logger.log(Level.INFO, "executing CQL " + serviceName); int count = client.searchCQL(query, from, size, (status, total, returned, elapsedMillis) -> @@ -44,7 +44,7 @@ class DefaultClientTest { String query = "@attr 1=8 \"00280836\""; int from = 1; int size = 10; - try (DefaultClient client = newZClient(serviceName)) { + try (JDKZClient client = newZClient(serviceName)) { logger.log(Level.INFO, "executing PQF " + serviceName); int count = client.searchPQF(query, from, size, (status, total, returned, elapsedMillis) -> @@ -57,7 +57,7 @@ class DefaultClientTest { } } - private DefaultClient newZClient(String name) throws IOException { + private JDKZClient newZClient(String name) throws IOException { return newZClient(getProperties(name)); } @@ -69,8 +69,8 @@ class DefaultClientTest { return properties; } - private static DefaultClient newZClient(Properties properties) { - DefaultClient.Builder builder = DefaultClient.builder(); + private static JDKZClient newZClient(Properties properties) { + JDKZClient.Builder builder = JDKZClient.builder(); if (properties.containsKey("host")) { builder.setHost(properties.getProperty("host")); } diff --git a/z3950-client/src/test/java/org/xbib/z3950/client/test/GBVZClientTest.java b/z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/GBVZClientTest.java similarity index 90% rename from z3950-client/src/test/java/org/xbib/z3950/client/test/GBVZClientTest.java rename to z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/GBVZClientTest.java index 80b119f..2ae6db0 100644 --- a/z3950-client/src/test/java/org/xbib/z3950/client/test/GBVZClientTest.java +++ b/z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/GBVZClientTest.java @@ -1,7 +1,7 @@ -package org.xbib.z3950.client.test; +package org.xbib.z3950.client.jdk.test; import org.junit.jupiter.api.Test; -import org.xbib.z3950.client.DefaultClient; +import org.xbib.z3950.client.jdk.JDKZClient; import java.io.IOException; import java.io.InputStream; @@ -25,7 +25,7 @@ class GBVZClientTest { String query = "@attr 1=4 linux"; int from = 1; int size = 10; - try (DefaultClient client = newZClient("GBV")) { + try (JDKZClient client = newZClient("GBV")) { logger.log(Level.INFO, "executing PQF " + query); int count = client.searchPQF(query, from, size, (status, total, returned, elapsedMillis) -> @@ -43,7 +43,7 @@ class GBVZClientTest { String query = "bib.controlNumberZDB = 1413423-8"; int from = 1; int size = 2; - try (DefaultClient client = newZClient(serviceName)) { + try (JDKZClient client = newZClient(serviceName)) { logger.log(Level.INFO, "executing CQL " + query); int count = client.searchCQL(query, from, size, (status, total, returned, elapsedMillis) -> @@ -57,7 +57,7 @@ class GBVZClientTest { } - private DefaultClient newZClient(String name) throws IOException { + private JDKZClient newZClient(String name) throws IOException { return newZClient(getProperties(name)); } @@ -69,8 +69,8 @@ class GBVZClientTest { return properties; } - private static DefaultClient newZClient(Properties properties) { - DefaultClient.Builder builder = DefaultClient.builder(); + private static JDKZClient newZClient(Properties properties) { + JDKZClient.Builder builder = JDKZClient.builder(); if (properties.containsKey("host")) { builder.setHost(properties.getProperty("host")); } diff --git a/z3950-client/src/test/java/org/xbib/z3950/client/test/SearchTest.java b/z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/SearchTest.java similarity index 91% rename from z3950-client/src/test/java/org/xbib/z3950/client/test/SearchTest.java rename to z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/SearchTest.java index 3eb13aa..d0791a5 100644 --- a/z3950-client/src/test/java/org/xbib/z3950/client/test/SearchTest.java +++ b/z3950-client-jdk/src/test/java/org/xbib/z3950/client/jdk/test/SearchTest.java @@ -1,9 +1,9 @@ -package org.xbib.z3950.client.test; +package org.xbib.z3950.client.jdk.test; import org.junit.jupiter.api.Test; import org.xbib.z3950.common.exceptions.MessageSizeTooSmallException; import org.xbib.z3950.common.exceptions.NoRecordsReturnedException; -import org.xbib.z3950.client.DefaultClient; +import org.xbib.z3950.client.jdk.JDKZClient; import java.util.Collections; import java.util.logging.Level; @@ -27,7 +27,7 @@ class SearchTest { int from = 1; int length = 1; try { - DefaultClient client = DefaultClient.builder() + JDKZClient client = JDKZClient.builder() .setHost(host) .setPort(port) .setDatabases(Collections.singletonList(database)) diff --git a/z3950-client-netty/build.gradle b/z3950-client-netty/build.gradle index b8dc1d1..f2db9a3 100644 --- a/z3950-client-netty/build.gradle +++ b/z3950-client-netty/build.gradle @@ -1,5 +1,8 @@ dependencies { - api project(':z3950-common') + api project(':z3950-client-api') + implementation "io.netty:netty-buffer:${project.property('netty.version')}" + implementation "io.netty:netty-common:${project.property('netty.version')}" implementation "io.netty:netty-handler:${project.property('netty.version')}" implementation "io.netty:netty-transport:${project.property('netty.version')}" + testImplementation "org.xbib:bibliographic-character-sets:${project.property('xbib-bibliographic-character-sets.version')}" } diff --git a/z3950-client-netty/src/main/java/module-info.java b/z3950-client-netty/src/main/java/module-info.java index fb5ae51..5b53536 100644 --- a/z3950-client-netty/src/main/java/module-info.java +++ b/z3950-client-netty/src/main/java/module-info.java @@ -1,6 +1,9 @@ module org.xbib.z3950lib.client.netty { exports org.xbib.z3950.client.netty; - requires transitive org.xbib.z3950lib.common; + requires transitive org.xbib.z3950lib.client.api; + requires io.netty.buffer; + requires io.netty.common; requires io.netty.handler; requires io.netty.transport; + requires java.logging; } diff --git a/z3950-client-netty/src/main/java/org/xbib/z3950/client/netty/NettyZClient.java b/z3950-client-netty/src/main/java/org/xbib/z3950/client/netty/NettyZClient.java index 93c5495..d079fa2 100644 --- a/z3950-client-netty/src/main/java/org/xbib/z3950/client/netty/NettyZClient.java +++ b/z3950-client-netty/src/main/java/org/xbib/z3950/client/netty/NettyZClient.java @@ -13,12 +13,19 @@ import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.util.CharsetUtil; +import org.xbib.z3950.api.RecordListener; +import org.xbib.z3950.api.ScanListener; +import org.xbib.z3950.api.SearchListener; +import org.xbib.z3950.client.api.Client; +import java.io.Closeable; +import java.io.IOException; import java.net.InetSocketAddress; +import java.util.List; /** * */ -public class NettyZClient { +public class NettyZClient implements Client, Closeable { private final EventLoopGroup group; private final Bootstrap clientBootstrap; @@ -46,6 +53,86 @@ public class NettyZClient { group.shutdownGracefully().sync(); } + @Override + public void close() throws IOException { + + } + + @Override + public int searchCQL(String query, int offset, int length, SearchListener searchListener, RecordListener recordListener) throws IOException { + return 0; + } + + @Override + public int searchPQF(String query, int offset, int length, SearchListener searchListener, RecordListener recordListener) throws IOException { + return 0; + } + + @Override + public void scanPQF(String query, int nTerms, int step, int position, ScanListener scanListener) throws IOException { + + } + + @Override + public String getHost() { + return null; + } + + @Override + public int getPort() { + return 0; + } + + @Override + public String getUser() { + return null; + } + + @Override + public String getPass() { + return null; + } + + @Override + public long getTimeout() { + return 0; + } + + @Override + public String getPreferredRecordSyntax() { + return null; + } + + @Override + public String getResultSetName() { + return null; + } + + @Override + public String getElementSetName() { + return null; + } + + @Override + public String getEncoding() { + return null; + } + + @Override + public String getFormat() { + return null; + } + + @Override + public String getType() { + return null; + } + + @Override + public List getDatabases() { + return null; + } + class Handler extends SimpleChannelInboundHandler { @Override diff --git a/z3950-client/src/main/java/module-info.java b/z3950-client/src/main/java/module-info.java deleted file mode 100644 index 4e25d0b..0000000 --- a/z3950-client/src/main/java/module-info.java +++ /dev/null @@ -1,5 +0,0 @@ -module org.xbib.z3950lib.client { - exports org.xbib.z3950.client; - requires transitive org.xbib.z3950lib.common; - requires java.logging; -} \ No newline at end of file diff --git a/z3950-common/src/main/java/org/xbib/z3950/common/cql/CQLRPNGenerator.java b/z3950-common/src/main/java/org/xbib/z3950/common/cql/CQLRPNGenerator.java index 5d33953..6648350 100644 --- a/z3950-common/src/main/java/org/xbib/z3950/common/cql/CQLRPNGenerator.java +++ b/z3950-common/src/main/java/org/xbib/z3950/common/cql/CQLRPNGenerator.java @@ -32,6 +32,7 @@ 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.Collection; import java.util.HashMap; import java.util.Map; import java.util.MissingResourceException; @@ -70,6 +71,12 @@ public final class CQLRPNGenerator implements Visitor { this.result = new Stack<>(); } + public CQLRPNGenerator(Collection attributeElements) { + this.attributeElements = new Stack<>(); + this.attributeElements.addAll(attributeElements); + this.result = new Stack<>(); + } + public RPNQuery getQueryResult() { return rpnQuery; } @@ -196,7 +203,8 @@ public final class CQLRPNGenerator implements Visitor { operand.attrTerm.term.c_general = new ASN1OctetString(node.getTerm().getValue()); } operand.attrTerm.attributes = new AttributeList(); - operand.attrTerm.attributes.value = attributeElements.toArray(new AttributeElement[0]); + operand.attrTerm.attributes.value = attributeElements.stream() + .filter(ae -> ae.attributeValue != null).toArray(AttributeElement[]::new); RPNStructure rpn = new RPNStructure(); rpn.c_op = operand; result.push(rpn); @@ -307,25 +315,17 @@ public final class CQLRPNGenerator implements Visitor { private ASN1OctetString transformTerm(Term term) { String v = term.getValue(); - // let's derive attributes from the search term + // let's derive attributes from the search term syntax // 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); + push(attributeElements, createAttributeElement(attributeType, attributeValue)); // 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); + //attributeType = 3; + // attributeValue = 3; // any position = 3 + //push(attributeElements, createAttributeElement(attributeType, attributeValue)); // structure attribute = 4 attributeType = 4; @@ -334,11 +334,7 @@ public final class CQLRPNGenerator implements Visitor { 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); + push(attributeElements, createAttributeElement(attributeType, attributeValue)); // truncation attribute = 5 attributeType = 5; @@ -355,12 +351,27 @@ public final class CQLRPNGenerator implements Visitor { 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); - + push(attributeElements, createAttributeElement(attributeType, attributeValue)); return new ASN1OctetString(v); } + + private static void push(Stack stack, AttributeElement attributeElement) { + if (attributeElement != null) { + if (!stack.contains(attributeElement)) { + stack.push(attributeElement); + } + } + } + + private static AttributeElement createAttributeElement(Integer attributeType, Integer attributeValue) { + if (attributeType != null && attributeValue != null) { + AttributeElement ae = new AttributeElement(); + ae.attributeType = new ASN1Integer(attributeType); + ae.attributeValue = new AttributeElementAttributeValue(); + ae.attributeValue.numeric = new ASN1Integer(attributeValue); + return ae; + } else { + return null; + } + } } diff --git a/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequest.java b/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequest.java index ddebe2b..f0ceda6 100644 --- a/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequest.java +++ b/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequest.java @@ -120,7 +120,7 @@ public final class AccessControlRequest extends ASN1Any { if (sOtherInfo != null) { numFields++; } - BEREncoding fields[] = new BEREncoding[numFields]; + BEREncoding[] fields = new BEREncoding[numFields]; int x = 0; if (sReferenceId != null) { fields[x++] = sReferenceId.berEncode(); @@ -149,11 +149,8 @@ public final class AccessControlRequest extends ASN1Any { } str.append("securityChallenge "); str.append(sSecurityChallenge); - outputted++; if (sOtherInfo != null) { - if (0 < outputted) { - str.append(", "); - } + str.append(", "); str.append("otherInfo "); str.append(sOtherInfo); } diff --git a/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequestSecurityChallenge.java b/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequestSecurityChallenge.java index 535f02f..ec5e711 100644 --- a/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequestSecurityChallenge.java +++ b/z3950-common/src/main/java/org/xbib/z3950/common/v3/AccessControlRequestSecurityChallenge.java @@ -82,7 +82,7 @@ public final class AccessControlRequestSecurityChallenge extends ASN1Any { @Override public BEREncoding berEncode() throws ASN1Exception { BEREncoding chosen = null; - BEREncoding enc[]; + BEREncoding[] enc; if (cSimpleForm != null) { chosen = cSimpleForm.berEncode(BEREncoding.CONTEXT_SPECIFIC_TAG, 37); } diff --git a/z3950-common/src/main/java/org/xbib/z3950/common/v3/AttributeElement.java b/z3950-common/src/main/java/org/xbib/z3950/common/v3/AttributeElement.java index 95079f8..80f586a 100644 --- a/z3950-common/src/main/java/org/xbib/z3950/common/v3/AttributeElement.java +++ b/z3950-common/src/main/java/org/xbib/z3950/common/v3/AttributeElement.java @@ -19,7 +19,7 @@ import org.xbib.asn1.BEREncoding; * } * */ -public final class AttributeElement extends ASN1Any { +public final class AttributeElement extends ASN1Any implements Comparable { public AttributeSetId attributeSetId; // optional @@ -125,7 +125,7 @@ public final class AttributeElement extends ASN1Any { if (attributeSetId != null) { numFields++; } - BEREncoding fields[] = new BEREncoding[numFields]; + BEREncoding[] fields = new BEREncoding[numFields]; int x = 0; if (attributeSetId != null) { fields[x++] = attributeSetId.berEncode(BEREncoding.CONTEXT_SPECIFIC_TAG, 1); @@ -153,13 +153,15 @@ public final class AttributeElement extends ASN1Any { } str.append("attributeType "); str.append(attributeType); - outputted++; - if (0 < outputted) { - str.append(", "); - } + str.append(", "); str.append("attributeValue "); str.append(attributeValue); str.append("}"); return str.toString(); } + + @Override + public int compareTo(AttributeElement o) { + return attributeType.toString().compareTo(o.attributeType.toString()); + } } diff --git a/z3950-common/src/test/java/org/xbib/z3950/common/cql/CQL2RPNTest.java b/z3950-common/src/test/java/org/xbib/z3950/common/cql/CQL2RPNTest.java index 08e5d25..6544263 100644 --- a/z3950-common/src/test/java/org/xbib/z3950/common/cql/CQL2RPNTest.java +++ b/z3950-common/src/test/java/org/xbib/z3950/common/cql/CQL2RPNTest.java @@ -2,7 +2,11 @@ package org.xbib.z3950.common.cql; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import org.xbib.asn1.ASN1Integer; import org.xbib.cql.CQLParser; +import org.xbib.z3950.common.v3.AttributeElement; +import org.xbib.z3950.common.v3.AttributeElementAttributeValue; +import java.util.Collections; class CQL2RPNTest { @@ -14,7 +18,7 @@ class CQL2RPNTest { 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 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 2, attributeValue {numeric 3}}{attributeType 4, attributeValue {numeric 2}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"Test\"}}}}}", q); } @Test @@ -25,6 +29,19 @@ class CQL2RPNTest { 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); + 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); + } + + @Test + void testWithAttribute() { + AttributeElement ae = new AttributeElement(); + ae.attributeType = new ASN1Integer(2); + String cql = "dc.title = \"a phrase\""; + CQLParser parser = new CQLParser(cql); + parser.parse(); + CQLRPNGenerator generator = new CQLRPNGenerator(Collections.singleton(ae)); + 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 4, attributeValue {numeric 1}}{attributeType 5, attributeValue {numeric 100}}{attributeType 1, attributeValue {numeric 4}}}, term {general \"a phrase\"}}}}}", q); } }