diff --git a/service-csw/pom.xml b/service-csw/pom.xml index 402db1bb7d..e48851c122 100755 --- a/service-csw/pom.xml +++ b/service-csw/pom.xml @@ -27,14 +27,14 @@ org.mybatis mybatis - + org.oskari - service-control - - - javax.vecmath - vecmath - + service-control + + + javax.vecmath + vecmath + junit @@ -51,16 +51,16 @@ postgresql test - - com.fasterxml.jackson.core - jackson-core - + + com.fasterxml.jackson.core + jackson-core + org.oskari shared-test-resources test - + diff --git a/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueChannelSearchService.java b/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueChannelSearchService.java index 8e23d1e4be..2e939872cb 100755 --- a/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueChannelSearchService.java +++ b/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueChannelSearchService.java @@ -38,8 +38,8 @@ * * Configurable by properties: * - Server: service.metadata.url (for example "https://www.paikkatietohakemisto.fi/geonetwork/srv/fin/csw") - * - localized urls for images: search.channel.METADATA_CATALOGUE_CHANNEL.image.url.[lang code] (as contentURL in conjunction with resourceId) - * - localized urls for service: search.channel.METADATA_CATALOGUE_CHANNEL.fetchpage.url.[lang code] (as actionURL in conjunction with resourceId) + * - Query type: search.channel.METADATA_CATALOGUE_CHANNEL.queryType (defaults to "summary") + * - Query fields: search.channel.METADATA_CATALOGUE_CHANNEL.queryFields (comma-separted list like "Title, Abstract" - defaults to "csw:anyText") * - advanced filter fields (dropdowns) that are available on form based on the service: * search.channel.METADATA_CATALOGUE_CHANNEL.fields (Note! Uses GetDomain Operation on CSW to populate values for fields) * - per field processing definitions (each property prefixed with "search.channel.METADATA_CATALOGUE_CHANNEL.field.[field name]."): @@ -61,6 +61,8 @@ public class MetadataCatalogueChannelSearchService extends SearchChannel { public static final String ID = "METADATA_CATALOGUE_CHANNEL"; private static String serverURL = PropertyUtil.get(PROP_SERVICE_URL); + private String queryType; + private String[] queryFields; private final static List fields = new ArrayList<>(); @@ -68,25 +70,13 @@ public class MetadataCatalogueChannelSearchService extends SearchChannel { private final MetadataCatalogueQueryHelper QUERY_HELPER = new MetadataCatalogueQueryHelper(); private OskariLayerService mapLayerService = OskariComponentManager.getComponentOfType(OskariLayerService.class); - private static final String PROPERTY_RESULTPARSER = "search.channel.METADATA_CATALOGUE_CHANNEL.resultparser"; @Override public void init() { super.init(); - // hook for customized parsing - // TODO: this was only used for ELF to inject rating for metadata. We can probably remove it now - final String customResultParser = PropertyUtil.getOptional(PROPERTY_RESULTPARSER); - if (customResultParser != null) { - try { - final Class clazz = Class.forName(customResultParser); - RESULT_PARSER = (MetadataCatalogueResultParser) clazz.newInstance(); - } catch (Exception e) { - log.error(e, "Error instantiating custom metadata result parser:", customResultParser); - } - } - if (RESULT_PARSER == null) { - RESULT_PARSER = new MetadataCatalogueResultParser(); - } + queryType = getProperty("queryType", "summary"); + queryFields = getProperty("queryFields", "csw:anyText").split("\\s*,\\s*"); + RESULT_PARSER = new MetadataCatalogueResultParser(); } /** @@ -176,19 +166,10 @@ public ChannelSearchResult parseResults(Element root, SearchCriteria searchCrite getResults(root).forEach(metadata -> { try { final SearchResultItem item = RESULT_PARSER.parseResult(metadata); -/* -// done in frontend now? - final List oskariLayers = getOskariLayerWithUuid(item); - for(OskariLayer oskariLayer : oskariLayers){ - log.debug("METAID: " + oskariLayer.getMetadataId()); - item.addUuId(oskariLayer.getMetadataId()); - } - */ - item.addValue("geom", getWKT(item, WKTHelper.PROJ_EPSG_4326, srs)); channelSearchResult.addItem(item); } catch (Exception e) { - log.warn(e); + log.info("Error parsing metadata search result item", e); } }); @@ -238,7 +219,7 @@ private String getWKT(final SearchResultItem item, final String sourceSRS, final private Element makeQuery(SearchCriteria searchCriteria) throws Exception { final long start = System.currentTimeMillis(); - final String payload = QUERY_HELPER.getQueryPayload(searchCriteria); + final String payload = QUERY_HELPER.getQueryPayload(searchCriteria, queryType, queryFields); if (payload == null) { // no point in making the query without payload return null; diff --git a/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueQueryHelper.java b/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueQueryHelper.java index 106fc2c8ba..49e6d3b33f 100644 --- a/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueQueryHelper.java +++ b/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueQueryHelper.java @@ -24,6 +24,8 @@ import java.util.List; import java.util.Map; +import static org.oskari.csw.request.GetRecords.DEFAULT_QUERY_TYPE; + /** * Helper class for creating search queries for MetadataCatalogue */ @@ -35,6 +37,7 @@ public class MetadataCatalogueQueryHelper { public final static String WILDCARD_CHARACTER = "*"; public final static String SINGLE_WILDCARD_CHARACTER = "?"; public final static String ESCAPE_CHARACTER = "/"; + private static final String[] DEFAULT_QUERY_FIELDS = new String[] { "csw:anyText" }; private static final Logger log = LogFactory.getLogger(MetadataCatalogueQueryHelper.class); private FilterFactory2 filterFactory; @@ -45,7 +48,10 @@ public MetadataCatalogueQueryHelper() { } public String getQueryPayload(SearchCriteria searchCriteria) { - final List filters = getFiltersForQuery(searchCriteria); + return getQueryPayload(searchCriteria, DEFAULT_QUERY_TYPE, DEFAULT_QUERY_FIELDS); + } + public String getQueryPayload(SearchCriteria searchCriteria, String queryType, String... queryFields) { + final List filters = getFiltersForQuery(searchCriteria, queryFields); if (filters.isEmpty()) { // no point in making the query without GetRecords, but throw exception instead? //throw new ServiceRuntimeException("Can't create GetRecords request without filters"); @@ -58,19 +64,27 @@ public String getQueryPayload(SearchCriteria searchCriteria) { filter = filterFactory.and(filters); } - return GetRecords.createRequest(filter); + return GetRecords.createRequest(filter, queryType); } - private List getFiltersForQuery(SearchCriteria searchCriteria) { + private List getFiltersForQuery(SearchCriteria searchCriteria, String... queryFields) { final List list = new ArrayList<>(); final List theOrList = new ArrayList<>(); // user input - Filter userInput = createLikeFilter(searchCriteria.getSearchString(), "csw:anyText"); - if (userInput != null) { - list.add(userInput); + if (queryFields == null || queryFields.length == 0) { + queryFields = DEFAULT_QUERY_FIELDS; } - + List queryFilters = new ArrayList<>(); + for (String field: queryFields) { + queryFilters.add(createLikeFilter(searchCriteria.getSearchString(), field)); + } + if (queryFilters.size() == 1) { + list.add(queryFilters.get(0)); + } else if (queryFilters.size() > 1) { + list.add(filterFactory.or(queryFilters)); + } + // "advanced fields" for (MetadataField field : MetadataCatalogueChannelSearchService.getFields()) { final Filter operation = getFilterForField(searchCriteria, field); if (operation == null) { diff --git a/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueResultParser.java b/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueResultParser.java index 4f6f320f6b..737d4aec37 100755 --- a/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueResultParser.java +++ b/service-csw/src/main/java/fi/nls/oskari/search/channel/MetadataCatalogueResultParser.java @@ -16,8 +16,6 @@ */ public class MetadataCatalogueResultParser { - private static final Logger log = LogFactory.getLogger(MetadataCatalogueResultParser.class); - public static final String KEY_IDENTIFICATION = "identification"; public static final String KEY_IDENTIFICATION_DATE = "date"; public static final String KEY_IDENTIFICATION_CODELIST = "code"; @@ -42,7 +40,6 @@ public SearchResultItem parseResult(final Element elem) throws Exception { XmlHelper.getFirstChild(elem, "fileIdentifier"), "CharacterString"); item.setResourceId(uuid); - //item.addUuId(uuid); // lang Element languageCode = XmlHelper.getFirstChild( XmlHelper.getFirstChild(elem, "language"), diff --git a/service-csw/src/main/java/org/oskari/csw/request/GetRecords.java b/service-csw/src/main/java/org/oskari/csw/request/GetRecords.java index cdc8b7a677..0db38e8f97 100644 --- a/service-csw/src/main/java/org/oskari/csw/request/GetRecords.java +++ b/service-csw/src/main/java/org/oskari/csw/request/GetRecords.java @@ -18,21 +18,25 @@ public class GetRecords { private static final String CSW_VERSION = "2.0.2"; private static final String CONSTRAINT_VERSION = "1.0.0"; + public static final String DEFAULT_QUERY_TYPE = "summary"; private GetRecords() {} + public static String createRequest(Filter filter) { + return createRequest(filter, DEFAULT_QUERY_TYPE); + } /** * Builds a GetRecords request payload for CSW-service with the given filters. * @param filter required * @return */ - public static String createRequest(Filter filter) { + public static String createRequest(Filter filter, String queryType) { if (filter == null) { throw new ServiceRuntimeException("Filter is required"); } final StringWriter writer = new StringWriter(); XMLStreamWriter xsw = getXMLWriter(writer); - startDocument(xsw); + startDocument(xsw, queryType); writeRawXMLUnsafe(xsw, writer, getFilterAsString(filter)); endDocument(xsw); return writer.toString(); @@ -59,7 +63,7 @@ private static XMLStreamWriter getXMLWriter(Writer writer) { ... */ - private static void startDocument(XMLStreamWriter xsw) { + private static void startDocument(XMLStreamWriter xsw, String queryType) { try { xsw.writeStartDocument(); xsw.writeStartElement("csw", "GetRecords", CSW_URI); @@ -72,7 +76,7 @@ private static void startDocument(XMLStreamWriter xsw) { xsw.writeAttribute("service", "CSW"); xsw.writeAttribute("version", CSW_VERSION); - xsw.writeAttribute("maxRecords", "10000"); + xsw.writeAttribute("maxRecords", "100"); xsw.writeAttribute("startPosition", "1"); xsw.writeAttribute("resultType", "results"); // or "validate" or "hits" @@ -90,7 +94,15 @@ private static void startDocument(XMLStreamWriter xsw) { // parse but it's safe. xsw.writeStartElement(CSW_URI, "ElementSetName"); // changes from full to summary for performance reasons. "brief" would be even faster but doesn't include dates - xsw.writeCharacters("summary"); + String type = queryType; + // these are the valid values + if (type == null) { + type = "summary"; + } + if (!("summary".equals(type) || "brief".equals(type) || "full".equals(type))) { + throw new IllegalArgumentException("Type needs to be one of: summary, brief, full. Was: " + type); + } + xsw.writeCharacters(type); xsw.writeEndElement(); // ElementSetName diff --git a/service-csw/src/test/java/org/oskari/csw/request/GetRecordsTest.java b/service-csw/src/test/java/org/oskari/csw/request/GetRecordsTest.java index 1a223230c3..5564301810 100644 --- a/service-csw/src/test/java/org/oskari/csw/request/GetRecordsTest.java +++ b/service-csw/src/test/java/org/oskari/csw/request/GetRecordsTest.java @@ -48,6 +48,28 @@ public void testWithNoFilter() { fail("Should have thrown exception"); } + @Test + public void testRequestType() { + // build filter + Filter filter = createEqualsFilter("csw:Any", "testing"); + String request = org.oskari.csw.request.GetRecords.createRequest(filter); + + assertTrue("Should get 'summary' as request type", request.contains("summary")); + + request = org.oskari.csw.request.GetRecords.createRequest(filter, "brief"); + assertTrue("Should get 'brief' as request type", request.contains("brief")); + + request = org.oskari.csw.request.GetRecords.createRequest(filter, "full"); + assertTrue("Should get 'full' as request type", request.contains("full")); + } + + @Test(expected = IllegalArgumentException.class) + public void testRequestTypeInvalid() { + // build filter + Filter filter = createEqualsFilter("csw:Any", "testing"); + org.oskari.csw.request.GetRecords.createRequest(filter, "dummy"); + } + @Test public void testSimpleFilter() throws IOException, SAXException { // build filter diff --git a/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-coverage.xml b/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-coverage.xml index 678893dcfb..5c59abb3e3 100644 --- a/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-coverage.xml +++ b/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-coverage.xml @@ -2,7 +2,7 @@ summary diff --git a/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-multi.xml b/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-multi.xml index 618a998e95..fb8b6f777d 100644 --- a/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-multi.xml +++ b/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-multi.xml @@ -1,6 +1,6 @@ diff --git a/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-simple.xml b/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-simple.xml index e1fba9844b..6ceae17ae5 100644 --- a/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-simple.xml +++ b/service-csw/src/test/resources/org/oskari/csw/request/GetRecords-simple.xml @@ -1,6 +1,6 @@