Ignore:
Timestamp:
08/09/14 20:45:17 (10 years ago)
Author:
Oliver Schonefeld
Message:
  • support new FCS specification (with some backwards compatibility for old spec)

HEADS UP: not yet ready for release; needs more testing

File:
1 edited

Legend:

Unmodified
Added
Removed
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/SimpleEndpointSearchEngineBase.java

    r5485 r5546  
    11package eu.clarin.sru.server.fcs;
    22
    3 import java.util.ArrayList;
     3import java.net.URI;
    44import java.util.Collections;
    55import java.util.List;
     
    77
    88import javax.servlet.ServletContext;
     9import javax.xml.XMLConstants;
    910import javax.xml.stream.XMLStreamException;
    1011import javax.xml.stream.XMLStreamWriter;
     
    3031
    3132/**
    32  * A base class for implementing a simple search engine to be used as a CLARIN
    33  * FCS endpoint.
     33 * A base class for implementing a simple search engine to be used as a
     34 * CLARIN-FCS endpoint.
    3435 *
    3536 */
    3637public abstract class SimpleEndpointSearchEngineBase extends
    3738        SRUSearchEngineBase {
    38    
     39    private static final String X_FCS_ENDPOINT_DESCRIPTION = "x-fcs-endpoint-description";
    3940    private static final String X_CMD_RESOURCE_INFO = "x-cmd-resource-info";
    40     private static final String X_FCS_ENDPOINT_DESCRIPTION = "x-fcs-endpoint-description";
    41    
     41    private static final String ED_NS = "http://clarin.eu/fcs/endpoint-description";
     42    private static final String ED_PREFIX = "ed";
     43    private static final int ED_VERSION = 1;
     44    private static final String FCS_RESOURCE_INFO_NS = "http://clarin.eu/fcs/1.0/resource-info";
    4245    private static final String FCS_SCAN_INDEX_FCS_RESOURCE = "fcs.resource";
    4346    private static final String FCS_SCAN_INDEX_CQL_SERVERCHOICE = "cql.serverChoice";
     
    4750    private static final Logger logger =
    4851            LoggerFactory.getLogger(SimpleEndpointSearchEngineBase.class);
    49     protected ResourceInfoInventory resourceInfoInventory;
    50    
    51     public List<String> capabilities;
    52     public List<DataView> supportedDataViews;
    53    
    54     public void addEndpointCapability(String c){
    55         capabilities.add(c);
    56     }
    57    
    58     public void addDataView(DataView d){
    59         supportedDataViews.add(d);
    60     }   
    61        
    62     public void setCapabilities(){
    63          logger.debug("Setting basic capability");
    64          capabilities = new ArrayList<String>();
    65          capabilities.add("http://clarin.eu/fcs/capability/basic-search");
    66     }     
    67    
    68     public void setSupportedDataViews(){
    69          logger.debug("Setting Generic Hits dataview");
    70          supportedDataViews = new ArrayList<DataView>();
    71          supportedDataViews.add(
    72                         new DataView("The representation of the hit",
    73                                 "application/x-clarin-fcs-hits+xml",
    74                                 DataView.PayloadDisposition.INLINE,
    75                                 DataView.PayloadDelivery.SEND_BY_DEFAULT,
    76                                 "hits")
    77          );
    78     }
    79    
    80         /**
     52    protected EndpointDescription endpointDescription;
     53
     54
     55    /**
    8156     * This method should not be overridden. Perform your custom initialization
    8257     * in the {@link #doInit(ServletContext, SRUServerConfig, Map)} method
     
    8964            Map<String, String> params) throws SRUConfigException {
    9065        logger.debug("initializing");
    91         super.init(context, config, params);             
    92        
     66        super.init(context, config, params);
     67
    9368        logger.debug("initializing search engine implementation");
    9469        doInit(context, config, params);
    95                
    96         logger.debug("initizalizing resource info inventory");
    97         this.resourceInfoInventory = createResourceInfoInventory(context, config, params);
    98         if (this.resourceInfoInventory == null) {
    99             logger.error("ClarinFCSSearchEngineBase implementation error: " +
    100                     "initResourceCatalog() returned null");
    101             throw new SRUConfigException("initResourceCatalog() returned no " +
    102                     "valid implementation of a ResourceCatalog");
     70
     71        logger.debug("initizalizing endpoint description");
     72        this.endpointDescription =
     73                createEndpointDescription(context, config, params);
     74        if (this.endpointDescription == null) {
     75            logger.error("SimpleEndpointSearchEngineBase implementation " +
     76                    "error: createEndpointDescription() returned null");
     77            throw new SRUConfigException("createEndpointDescription() " +
     78                    "returned no valid implementation of an EndpointDescription");
    10379        }
    10480    }
     
    11389    @Override
    11490    public final void destroy() {
    115         logger.debug("performing cleanup of resource info inventory");
    116         resourceInfoInventory.destroy();
     91        logger.debug("performing cleanup of endpoint description");
     92        endpointDescription.destroy();
    11793        logger.debug("performing cleanup of search engine");
    11894        doDestroy();
     
    125101            SRURequest request, SRUDiagnosticList diagnostics)
    126102            throws SRUException {
    127        
    128         final boolean provideCmdResourceInfo =
    129                 parseBoolean(request.getExtraRequestData(X_CMD_RESOURCE_INFO));
    130         final boolean provideFcsResourceInfo =
    131                 parseBoolean(request.getExtraRequestData(X_FCS_ENDPOINT_DESCRIPTION));
    132                
    133         if (provideCmdResourceInfo) {
    134             final List<ResourceInfo> resourceInfoList =
    135                     resourceInfoInventory.getResourceInfoList(
    136                             ResourceInfoInventory.PID_ROOT);
    137            
     103
     104        final boolean provideEndpointDescription =
     105                parseBoolean(request.getExtraRequestData(
     106                        X_FCS_ENDPOINT_DESCRIPTION));
     107
     108        if (provideEndpointDescription) {
    138109            return new SRUExplainResult(diagnostics) {
    139110                @Override
    140111                public boolean hasExtraResponseData() {
    141                     return provideCmdResourceInfo;
    142                 }
     112                    return provideEndpointDescription;
     113                }
     114
     115
    143116                @Override
    144117                public void writeExtraResponseData(XMLStreamWriter writer)
    145118                        throws XMLStreamException {
    146                     ResourceInfoWriter.writeFullResourceInfo(writer, null, resourceInfoList);
     119                    writeEndpointDescription(writer);
    147120                }
    148121            };
    149         }
    150         else if (provideFcsResourceInfo && capabilities != null
    151                         && supportedDataViews != null){
    152                
    153                 final List<ResourceInfo> resourceInfoList =
    154                     resourceInfoInventory.getResourceInfoList(
    155                             ResourceInfoInventory.PID_ROOT);
    156                
    157 //              if (capabilities == null){
    158 //                      throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
    159 //                                      "Capabilities are not set.");
    160 //              }
    161 //              if (supportedDataViews == null){
    162 //                      throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
    163 //                                      "Supported data views are not set.");
    164 //              }
    165                 return new SRUExplainResult(diagnostics) {
    166                 @Override
    167                 public boolean hasExtraResponseData() {
    168                     return provideFcsResourceInfo;
    169                 }
    170                 @Override
    171                 public void writeExtraResponseData(XMLStreamWriter writer)
    172                         throws XMLStreamException {
    173                         EndpointDescriptionWriter.writeEndpointDescription(writer,
    174                                 capabilities, supportedDataViews, resourceInfoList);
    175                 }
    176             };
    177         }
    178         else {
     122        } else {
    179123            return null;
    180124        }
     
    191135     */
    192136    @Override
    193     @Deprecated
    194137    public final SRUScanResultSet scan(SRUServerConfig config,
    195138            SRURequest request, SRUDiagnosticList diagnostics)
     
    215158             */
    216159            final boolean provideResourceInfo = parseBoolean(
    217                     request.getExtraRequestData(X_FCS_ENDPOINT_DESCRIPTION));
     160                    request.getExtraRequestData(X_CMD_RESOURCE_INFO));
    218161
    219162            return new SRUScanResultSet(diagnostics) {
     
    234177                @Override
    235178                public int getNumberOfRecords() {
    236                     return result.get(idx).getResourceCount();
     179                    return -1;
    237180                }
    238181
     
    260203                        throws XMLStreamException {
    261204                    if (provideResourceInfo) {
    262                         ResourceInfoWriter.writeResourceInfo(writer, null, result.get(idx));
     205                        writeLegacyResourceInfo(writer, result.get(idx));
    263206                    }
    264207                }
     
    270213
    271214
    272 
    273     /**
    274      * Create the resource info inventory to be used with this endpoint.
    275      * Implement this method to provide an implementation of a
    276      * {@link ResourceInfoInventory} that is tailored towards your environment
    277      * and needs.
    278      *
    279      * @param context
    280      *            the {@link ServletContext} for the Servlet
    281      * @param config
    282      *            the {@link SRUServerConfig} object for this search engine
    283      * @param params
    284      *            additional parameters gathered from the Servlet configuration
    285      *            and Servlet context.
    286      * @return an instance of a {@link ResourceInfoInventory} used by this
    287      *         search engine
    288      * @throws SRUConfigException
    289      *             if an error occurred
    290      */
    291     protected abstract ResourceInfoInventory createResourceInfoInventory(
     215    protected abstract EndpointDescription createEndpointDescription(
    292216            ServletContext context, SRUServerConfig config,
    293217            Map<String, String> params) throws SRUConfigException;
     
    328252     *      SRUDiagnosticList)
    329253     */
    330     @Deprecated
    331254    protected SRUScanResultSet doScan(SRUServerConfig config,
    332255            SRURequest request, SRUDiagnosticList diagnostics)
     
    364287    }
    365288
    366     @Deprecated
     289
    367290    private List<ResourceInfo> translateFcsScanResource(CQLNode scanClause)
    368291            throws SRUException {
     
    386309            }
    387310
     311            logger.warn("scan on 'fcs.resource' for endpoint resource " +
     312                    "enumeration is deprecated.");
    388313
    389314            // only allow "=" relation without any modifiers
     
    422347                    FCS_SCAN_INDEX_FCS_RESOURCE.equals(term)) ||
    423348                    (FCS_SCAN_INDEX_FCS_RESOURCE.equals(index))) {
    424                 results = resourceInfoInventory.getResourceInfoList(term);
     349                results = endpointDescription.getResourceList(term);
    425350            }
    426351            if ((results == null) || results.isEmpty()) {
     
    436361
    437362
    438    
     363    private void writeEndpointDescription(XMLStreamWriter writer)
     364            throws XMLStreamException {
     365        writer.setPrefix(ED_PREFIX, ED_NS);
     366        writer.writeStartElement(ED_NS, "EndpointDescription");
     367        writer.writeNamespace(ED_PREFIX, ED_NS);
     368        writer.writeAttribute("version", Integer.toString(ED_VERSION));
     369
     370        // capabilities
     371        writer.writeStartElement(ED_NS, "Capabilities");
     372        for (URI capability : endpointDescription.getCapabilities()) {
     373            writer.writeStartElement(ED_NS, "Capability");
     374            writer.writeCharacters(capability.toString());
     375            writer.writeEndElement(); // "Capability" element
     376        }
     377        writer.writeEndElement(); // "Capabilities" element
     378
     379        // supported data views
     380        writer.writeStartElement(ED_NS, "SupportedDataViews");
     381        for (DataView dataView : endpointDescription.getSupportedDataViews()) {
     382            writer.writeStartElement(ED_NS, "SupportedDataView");
     383            writer.writeAttribute("id", dataView.getIdentifier());
     384            String s;
     385            switch (dataView.getDeliveryPolicy()) {
     386            case SEND_BY_DEFAULT:
     387                s = "send-by-default";
     388                break;
     389            case NEED_TO_REQUEST:
     390                s = "need-to-request";
     391                break;
     392            default:
     393                throw new XMLStreamException(
     394                        "invalid value for payload delivery policy: " +
     395                                dataView.getDeliveryPolicy());
     396            } // switch
     397            writer.writeAttribute("delivery-policy", s);
     398            writer.writeCharacters(dataView.getMimeType());
     399            writer.writeEndElement(); // "SupportedDataView" element
     400        }
     401        writer.writeEndElement(); // "SupportedDataViews" element
     402
     403        try {
     404            // resources
     405            List<ResourceInfo> resources =
     406                    endpointDescription.getResourceList(
     407                            EndpointDescription.PID_ROOT);
     408            writeResourceInfos(writer, resources);
     409        } catch (SRUException e) {
     410            throw new XMLStreamException("error retriving top-level resources",
     411                    e);
     412        }
     413        writer.writeEndElement(); // "EndpointDescription" element
     414    }
     415
     416
     417    private void writeResourceInfos(XMLStreamWriter writer,
     418            List<ResourceInfo> resources) throws XMLStreamException {
     419        if (resources == null) {
     420            throw new NullPointerException("resources == null");
     421        }
     422        if (!resources.isEmpty()) {
     423            writer.writeStartElement(ED_NS, "Resources");
     424
     425            for (ResourceInfo resource : resources) {
     426                writer.writeStartElement(ED_NS, "Resource");
     427                writer.writeAttribute("pid", resource.getPid());
     428
     429                // title
     430                final Map<String, String> title = resource.getTitle();
     431                for (Map.Entry<String, String> i : title.entrySet()) {
     432                    writer.setPrefix(XMLConstants.XML_NS_PREFIX,
     433                            XMLConstants.XML_NS_URI);
     434                    writer.writeStartElement(ED_NS, "Title");
     435                    writer.writeAttribute(XMLConstants.XML_NS_URI, "lang", i.getKey());
     436                    writer.writeCharacters(i.getValue());
     437                    writer.writeEndElement(); // "title" element
     438                }
     439
     440                // description
     441                final Map<String, String> description = resource.getDescription();
     442                if (description != null) {
     443                    for (Map.Entry<String, String> i : description.entrySet()) {
     444                        writer.writeStartElement(ED_NS, "Description");
     445                        writer.writeAttribute(XMLConstants.XML_NS_URI, "lang",
     446                                i.getKey());
     447                        writer.writeCharacters(i.getValue());
     448                        writer.writeEndElement(); // "Description" element
     449                    }
     450                }
     451
     452                // landing page
     453                final String landingPageURI = resource.getLandingPageURI();
     454                if (landingPageURI != null) {
     455                    writer.writeStartElement(ED_NS, "LandingPageURI");
     456                    writer.writeCharacters(landingPageURI);
     457                    writer.writeEndElement(); // "LandingPageURI" element
     458                }
     459
     460                // languages
     461                final List<String> languages = resource.getLanguages();
     462                writer.writeStartElement(ED_NS, "Languages");
     463                for (String i : languages) {
     464                    writer.writeStartElement(ED_NS, "Language");
     465                    writer.writeCharacters(i);
     466                    writer.writeEndElement(); // "Language" element
     467
     468                }
     469                writer.writeEndElement(); // "Languages" element
     470
     471                // available data views
     472                StringBuilder sb = new StringBuilder();
     473                for (DataView dataview : resource.getAvailableDataViews()) {
     474                    if (sb.length() > 0) {
     475                        sb.append(" ");
     476                    }
     477                    sb.append(dataview.getIdentifier());
     478                }
     479                writer.writeEmptyElement(ED_NS, "AvailableDataViews");
     480                writer.writeAttribute("ref", sb.toString());
     481
     482                // child resources
     483                List<ResourceInfo> subs = resource.getSubResources();
     484                if ((subs != null) && !subs.isEmpty()) {
     485                    writeResourceInfos(writer, subs);
     486                }
     487
     488                writer.writeEndElement(); // "Resource" element
     489            }
     490            writer.writeEndElement(); // "Resources" element
     491        }
     492    }
     493
     494
     495    private void writeLegacyResourceInfo(XMLStreamWriter writer,
     496            ResourceInfo resourceInfo) throws XMLStreamException {
     497        writer.setDefaultNamespace(FCS_RESOURCE_INFO_NS);
     498        writer.writeStartElement(FCS_RESOURCE_INFO_NS, "ResourceInfo");
     499        writer.writeDefaultNamespace(FCS_RESOURCE_INFO_NS);
     500
     501        // title
     502        final Map<String, String> title = resourceInfo.getTitle();
     503        for (Map.Entry<String, String> i : title.entrySet()) {
     504            writer.setPrefix(XMLConstants.XML_NS_PREFIX,
     505                    XMLConstants.XML_NS_URI);
     506            writer.writeStartElement(FCS_RESOURCE_INFO_NS, "Title");
     507            writer.writeAttribute(XMLConstants.XML_NS_URI, "lang", i.getKey());
     508            writer.writeCharacters(i.getValue());
     509            writer.writeEndElement(); // "title" element
     510        }
     511
     512        // description
     513        final Map<String, String> description = resourceInfo.getDescription();
     514        if (description != null) {
     515            for (Map.Entry<String, String> i : description.entrySet()) {
     516                writer.writeStartElement(FCS_RESOURCE_INFO_NS, "Description");
     517                writer.writeAttribute(XMLConstants.XML_NS_URI, "lang",
     518                        i.getKey());
     519                writer.writeCharacters(i.getValue());
     520                writer.writeEndElement(); // "Description" element
     521            }
     522        }
     523
     524        // landing page
     525        final String landingPageURI = resourceInfo.getLandingPageURI();
     526        if (landingPageURI != null) {
     527            writer.writeStartElement(FCS_RESOURCE_INFO_NS, "LandingPageURI");
     528            writer.writeCharacters(landingPageURI);
     529            writer.writeEndElement(); // "LandingPageURI" element
     530        }
     531
     532        // languages
     533        final List<String> languages = resourceInfo.getLanguages();
     534        writer.writeStartElement(FCS_RESOURCE_INFO_NS, "Languages");
     535        for (String i : languages) {
     536            writer.writeStartElement(FCS_RESOURCE_INFO_NS, "Language");
     537            writer.writeCharacters(i);
     538            writer.writeEndElement(); // "Language" element
     539
     540        }
     541        writer.writeEndElement(); // "Languages" element
     542        writer.writeEndElement(); // "ResourceInfo" element
     543    }
     544
     545
     546//             final boolean defaultNS = ((prefix == null) || prefix.isEmpty());
     547//            if (writeNS) {
     548//                 if (defaultNS) {
     549//                     writer.setDefaultNamespace(FCS_RESOURCE_INFO_NS);
     550//                } else {
     551//                    writer.setPrefix(prefix, FCS_RESOURCE_INFO_NS);
     552//                }
     553//            }
     554//            writer.writeStartElement(FCS_RESOURCE_INFO_NS, "ResourceInfo");
     555//            if (writeNS) {
     556//                if (defaultNS) {
     557//                    writer.writeDefaultNamespace(FCS_RESOURCE_INFO_NS);
     558//                 } else {
     559//                    writer.writeNamespace(prefix, FCS_RESOURCE_INFO_NS);
     560//                 }
     561//          } )
     562//}
     563
     564//    public static void XwriteResourceInfo(XMLStreamWriter writer, String prefix,
     565//            ResourceInfo resourceInfo) throws XMLStreamException {
     566//        doWriteResourceInfo(writer, prefix, resourceInfo, true, false);
     567//    }
     568//
     569//
     570//    private static void XdoWriteResourceInfo(XMLStreamWriter writer,
     571//            String prefix, ResourceInfo resourceInfo, boolean writeNS,
     572//            boolean recursive) throws XMLStreamException {
     573//
     574//        if (writer == null) {
     575//            throw new NullPointerException("writer == null");
     576//        }
     577//        if (resourceInfo == null) {
     578//            throw new NullPointerException("resourceInfo == null");
     579//        }
     580//
     581//        final boolean defaultNS = ((prefix == null) || prefix.isEmpty());
     582//        if (writeNS) {
     583//            if (defaultNS) {
     584//                writer.setDefaultNamespace(FCS_RESOURCE_INFO_NS);
     585//            } else {
     586//                writer.setPrefix(prefix, FCS_RESOURCE_INFO_NS);
     587//            }
     588//        }
     589//        writer.writeStartElement(FCS_RESOURCE_INFO_NS, "Resource");
     590//        if (writeNS) {
     591//            if (defaultNS) {
     592//                writer.writeDefaultNamespace(FCS_RESOURCE_INFO_NS);
     593//            } else {
     594//                writer.writeNamespace(prefix, FCS_RESOURCE_INFO_NS);
     595//            }
     596//        }
     597//        if (recursive) {
     598//            /*
     599//             * HACK: only output @pid for recursive (= explain) requests.
     600//             * This should be revisited, if we decide to go for the explain
     601//             * style enumeration of resources.
     602//             */
     603//            writer.writeAttribute("pid", resourceInfo.getPid());
     604//        }
     605//        if (resourceInfo.hasSubResources()) {
     606//            writer.writeAttribute("hasSubResources", "true");
     607//        }
     608//
     609//
     610//        if (recursive && resourceInfo.hasSubResources()) {
     611//            writer.writeStartElement(FCS_RESOURCE_INFO_NS,
     612//                    "ResourceInfoCollection");
     613//            for (ResourceInfo r : resourceInfo.getSubResources()) {
     614//                doWriteResourceInfo(writer, prefix, r, writeNS, recursive);
     615//            }
     616//            writer.writeEndElement(); // "ResourceCollection" element
     617//        }
     618//        writer.writeEndElement(); // "ResourceInfo" element
     619//    }
    439620
    440621} // class SimpleEndpointSearchEngineBase
Note: See TracChangeset for help on using the changeset viewer.