ilscipio/scipio-erp

View on GitHub
applications/solr/servicedef/services.xml

Summary

Maintainability
Test Coverage
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is subject to the terms and conditions defined in the
files 'LICENSE' and 'NOTICE', which are part of this source
code package.
-->

<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.ofbiz.org/dtds/services.xsd">

    <description>Content Component Services</description>
    <vendor>Ilscipio GmbH</vendor>

    <service name="solrGenericPermission" engine="simple"
        location="component://solr/script/com/ilscipio/scipio/solr/SolrServices.xml" invoke="solrGenericPermission">
        <implements service="permissionInterface"/>
    </service>

    <!-- ========================================================= -->
    <!-- Status -->
    <!-- ========================================================= -->

    <service name="checkSolrReady" engine="java" use-transaction="false"
        location="com.ilscipio.scipio.solr.SolrProductSearch" invoke="checkSolrReady">
        <description>Checks if Solr webapp is loaded and available for queries</description>
        <attribute mode="IN" name="core" optional="true" type="String"/>
        <attribute mode="IN" name="client" optional="true" type="org.apache.solr.client.solrj.impl.HttpSolrClient"/>
        <attribute mode="OUT" name="ready" optional="true" type="Boolean">
            <description>True if Solr is enabled, loaded and available</description>
        </attribute>
        <attribute mode="OUT" name="enabled" optional="true" type="Boolean">
            <description>True if Solr is enabled, or it is registered as an application in the system
                (always true in stock Scipio config)</description>
        </attribute>
    </service>
    
    <service name="waitSolrReady" engine="java" use-transaction="false"
        location="com.ilscipio.scipio.solr.SolrProductSearch" invoke="waitSolrReady">
        <description>Returns only when Solr webapp is loaded and available for queries
            (returns failure if Solr is not registered in the system or other error)</description>
        <attribute mode="IN" name="core" optional="true" type="String"/>
        <attribute mode="IN" name="client" optional="true" type="org.apache.solr.client.solrj.impl.HttpSolrClient"/>
        <attribute mode="IN" name="sleepTime" optional="true" type="Integer">
            <description>Time (milliseconds) to wait between checks.
                Default: value of solrconfig.properties/solr.service.waitSolrReady.sleepTime</description>
        </attribute>
        <attribute mode="IN" name="maxChecks" optional="true" type="Integer">
            <description>Max number of times to check (-1 for infinite), separated by sleepTime.
                If passes this, returns failure. Default: value of solrconfig.properties/solr.service.waitSolrReady.maxChecks</description>
        </attribute>
    </service>

    <service name="setSolrDataStatus" engine="java"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="setSolrDataStatus">
        <description>Set SOLR data status ID</description>
        <attribute mode="IN" name="dataStatusId" optional="false" type="String" />
    </service>

    <service name="markSolrDataDirty" engine="java"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="markSolrDataDirty">
        <description>Mark SOLR data status as dirty</description>
    </service>

    <!-- ========================================================= -->
    <!-- Config -->
    <!-- ========================================================= -->

    <service name="setSolrSystemProperty" engine="java" location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="setSolrSystemProperty" auth="true">
        <permission-service service-name="solrGenericPermission" main-action="ADMIN"/>
        <attribute mode="IN" name="property" optional="false" type="String"/>
        <attribute mode="IN" name="value" optional="true" type="String"/>
        <attribute mode="IN" name="removeIfEmpty" optional="true" type="Boolean" default-value="false"/>
    </service>

    <service name="removeSolrSystemProperty" engine="java" location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="removeSolrSystemProperty" auth="true">
        <permission-service service-name="solrGenericPermission" main-action="ADMIN"/>
        <attribute mode="IN" name="property" optional="false" type="String"/>
    </service>

    <!-- ========================================================= -->
    <!-- Security -->
    <!-- ========================================================= -->
    
    <service name="reloadSolrSecurityAuthorizations" engine="java"
        use-transaction="false"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="reloadSolrSecurityAuthorizations">
        <description>Reloads the security authorizations defined in security.json</description>
        <permission-service service-name="solrGenericPermission" main-action="ADMIN"/>
    </service>

    <!-- ========================================================= -->
    <!-- Indexing -->
    <!-- ========================================================= -->

    <!-- Rebuild the Solr Tree -->
    <!-- NOTE: 2017-08-30: Now using semaphore="wait" (same as purgeOldJobs) to try to prevent concurrent executions
        doing strange things; this is more likely to happen now that SOLR_REBUILD_INIT job attempts retries on error, 
        but it could easily happen in other existing cases. -->
    <service name="rebuildSolrIndex" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="rebuildSolrIndex"
        semaphore="fail">
        <description>Rebuild Solr index, all products</description>
        <implements service="scipioJobCtxInterface"/>
        <attribute mode="IN" name="treatConnectErrorNonFatal" optional="true" type="Boolean" default-value="false" />
        <attribute mode="IN" name="core" optional="true" type="String" />
        <!-- 2016-03-29: If this flag is true, only rebuilds if SolrStatus.dataStatusId is not OK
            NOTE: unknown is treated as dirty. -->
        <attribute mode="IN" name="onlyIfDirty" optional="true" type="Boolean" default-value="false"/>
        <attribute mode="IN" name="ifConfigChange" optional="true" type="Boolean" default-value="false"/>
        <attribute mode="IN" name="bufSize" optional="true" type="Integer"/>
        <attribute mode="IN" name="clearAndUseCache" optional="true" type="Boolean">
            <description>see solrconfig.properties/solr.index.rebuild.clearAndUseCache</description>
        </attribute>
        <attribute mode="IN" name="waitSolrReady" optional="true" type="Boolean" default-value="false">
            <description>If true, will wait for Solr to be loaded before running the indexing- see waitSolrReady service</description><!-- Added 2018-02-20 -->
        </attribute>
        <attribute mode="IN" name="deleteMode" optional="true" type="String" default-value="no-delete">
            <description>How old records get cleared from index or not. Supported values:
                delete-all-first (clears whole index before reindexing, default),
                no-delete (deleted products will remain in solr index, can use when you know no products have changed since last indexing to minimize impact of reindex)</description><!-- Added 2020-03-12 -->
        </attribute>
        <attribute name="includeMainStoreIds" type="Collection" mode="IN" optional="true">
            <description>Only index products whose default/main store is one of these productStoreIds; warning: slow</description>
        </attribute>
        <attribute name="includeAnyStoreIds" type="Collection" mode="IN" optional="true">
            <description>Only index products linked to any of these productStoreIds; warning: slow</description>
        </attribute>
        <attribute mode="OUT" name="numDocs" optional="true" type="Integer" />
        <attribute mode="OUT" name="executed" optional="true" type="Boolean" />
    </service>

    <service name="rebuildSolrIndexNoDelete" engine="java"
             transaction-timeout="72000"
             location="com.ilscipio.scipio.solr.SolrProductSearch"
             invoke="rebuildSolrIndexNoDelete">
        <description>Rebuild Solr index, all products, without clearing index first</description>
        <implements service="rebuildSolrIndex"/>
        <attribute mode="IN" name="deleteMode" optional="true" type="String" default-value="no-delete"/>
    </service>

    <service name="rebuildSolrIndexIfDirty" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="rebuildSolrIndexIfDirty">
        <description>Rebuild Solr index, all products, if data status dirty or unknown or if config change</description>
        <implements service="rebuildSolrIndex"/>
        <attribute mode="IN" name="onlyIfDirty" optional="true" type="Boolean" default-value="true"/>
        <attribute mode="IN" name="ifConfigChange" optional="true" type="Boolean" default-value="true"/>
        <attribute mode="IN" name="waitSolrReady" optional="true" type="Boolean"/>
    </service>
    
    <service name="rebuildSolrIndexAuto" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="rebuildSolrIndexAuto">
        <description>rebuild SOLR Index - auto-run service</description>
        <implements service="rebuildSolrIndex"/>
        <!-- NOTE: MUST use attribute here, not override, to prevent default-value -->
        <attribute mode="IN" name="onlyIfDirty" optional="true" type="Boolean" />
        <attribute mode="IN" name="ifConfigChange" optional="true" type="Boolean"/>
        <attribute mode="IN" name="waitSolrReady" optional="true" type="Boolean"/>
    </service>

    <service name="abortRebuildSolrIndex" engine="java"
             location="com.ilscipio.scipio.solr.SolrProductSearch"
             invoke="abortRebuildSolrIndex" use-transaction="false">
        <description>Aborts rebuildSolrIndex if possible</description>
    </service>

    <service name="commitToSolr" engine="java" transaction-timeout="7200" location="com.ilscipio.scipio.solr.SolrProductSearch" invoke="commitToSolr" log="quiet"
        use-transaction="false">
        <description>Solr commit service, chained to entity indexing to receive documents</description>
        <implements service="entityIndexingConsumer"/>
    </service>

    <service name="updateToSolr" engine="java" location="com.ilscipio.scipio.solr.SolrProductSearch" invoke="updateToSolr"
        transaction-timeout="72000" priority="90">
        <description>Immediately adds OR removes product to/from solr index by product instance or by productId - intended for use with ECAs/SECAs,
            automatically called by registerUpdateToSolr</description>
        <implements service="scheduleProductIndexing"/>
        <override mode="IN" name="topics" type="List" optional="true" default-value="[solr]"/>
    </service>
    <service name="addToSolr" engine="java" location="com.ilscipio.scipio.solr.SolrProductSearch" invoke="addToSolr"
        transaction-timeout="72000" priority="90">
        <description>Immediately adds product to solr index by product instance or by productId, manual helper - NOT intended for use with ECAs/SECAs anymore (use registerUpdateToSolr/updateToSolr)</description>
        <implements service="updateToSolr"/>
        <override name="action" default-value="add"/>
    </service>
    <service name="removeFromSolr" engine="java" location="com.ilscipio.scipio.solr.SolrProductSearch" invoke="removeFromSolr" 
        transaction-timeout="72000" priority="90">
        <description>Immediately removes product from solr index by product instance or by productId, manual helper - NOT intended for use with ECAs/SECAs anymore (use registerUpdateToSolr/updateToSolr)</description>
        <implements service="updateToSolr"/>
        <override name="action" default-value="remove"/>
    </service>

    <!-- NOTE: ProductIndexingNow an alias for scheduleProductIndexing, also triggers non-solr product updates, left for compatibility, will not be removed -->
    <service name="registerUpdateToSolr" engine="java" location="com.ilscipio.scipio.solr.EntityIndexer" invoke="scheduleEntityIndexing"
        use-transaction="false" log="quiet" log-eca="quiet"><!-- must not force transaction; special behavior -->
        <description>Registers (queues) a product add or removal to/from solr index by product instance or by productId - intended for use with ECAs/SECAs
            - delays the solr index update (updateToSolr) to the current transaction's global-commit</description>
        <implements service="scheduleProductIndexing"/>
    </service>

    <service name="solrProductAttributesSimple" engine="interface">
        <description>Simple-type product attributes for addToSolrIndex Product
            NOTE: It is preferable to use the "fields" map of the addToSolrIndex interface in custom implementations,
            as is lessens the amount of patching required; solrProductAttributes* may be deprecated.</description>
        <!-- WARN: 2017-08-21: these are currently intermediate fields names that match may match neither Product entity nor solr product schema fields -->
        <!-- DEV NOTE: these should correspond to the old hardcoded list com.ilscipio.scipio.solr.SolrUtil.solrProdAttrSimple
            for backward compat, when a field is deprecated, move it back into addToSolrIndex interface -->
        <attribute mode="IN" name="productId" optional="true" type="String" /><!-- NOTE: 2019-08-01: Changed to optional="true" to generalize document indexing -->
        <attribute mode="IN" name="productTypeId" optional="true" type="String" />
        <attribute mode="IN" name="internalName" optional="true" type="String" />
        <attribute mode="IN" name="manu" optional="true" type="String" />
        <!-- TODO: REVIEW: size was hardcoded in com.ilscipio.scipio.solr.SolrUtil.solrProdAttrSimple but was not in interface nor schema...
        <attribute mode="IN" name="size" optional="true" type="String" /> -->

        <attribute mode="IN" name="smallImage" optional="true" type="String" />
        <attribute mode="IN" name="mediumImage" optional="true" type="String" />
        <attribute mode="IN" name="largeImage" optional="true" type="String" />

        <attribute mode="IN" name="listPrice" optional="true" type="String" />
        <attribute mode="IN" name="defaultPrice" optional="true" type="String" />
        
        <attribute mode="IN" name="inStock" optional="true" type="Integer" />
        <attribute mode="IN" name="isVirtual" optional="true" type="Boolean" />
        <attribute mode="IN" name="isVariant" optional="true" type="Boolean" />
        
        <attribute mode="IN" name="isDigital" optional="true" type="Boolean" />
        <attribute mode="IN" name="isPhysical" optional="true" type="Boolean" />
    </service>
    
    <service name="solrProductAttributesComplex" engine="interface">
        <description>Complex-type product attributes for addToSolrIndex Product
            NOTE: It is preferable to use the "fields" map of the addToSolrIndex interface in custom implementations,
                as is lessens the amount of patching required; solrProductAttributes* may be deprecated.</description>
        <!-- WARN: 2017-08-21: these are currently intermediate fields names that match may match neither Product entity nor solr product schema fields -->
        <attribute mode="IN" name="description" optional="true" type="Map" />
        <attribute mode="IN" name="longDescription" optional="true" type="Map" />
        <attribute mode="IN" name="title" optional="true" type="Map" />
        <attribute mode="IN" name="category" optional="true" type="List" />
        <attribute mode="IN" name="features" optional="true" type="Set" />
        <attribute mode="IN" name="attributes" optional="true" type="List" />
        <attribute mode="IN" name="catalog" optional="true" type="List" />
        <attribute mode="IN" name="keywords" optional="true" type="Object" /><!-- NOTE: un-deprecated 2017-09-12: can be String or List -->
        <attribute mode="IN" name="productStore" optional="true" type="List" /><!-- 2017-09-14 -->
    </service>

    <service name="solrProductAttributes" engine="interface">
        <description>All product attributes for addToSolrIndex Product
            NOTE: It is preferable to use the "fields" map of the addToSolrIndex interface in custom implementations,
            as is lessens the amount of patching required; solrProductAttributes* may be deprecated.</description>
        <!-- WARN: 2017-08-21: these are currently intermediate fields names that match may match neither Product entity nor solr product schema fields -->
        <implements service="solrProductAttributesSimple"/>
        <implements service="solrProductAttributesComplex"/>
    </service>

    <service name="addToSolrIndex" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="addToSolrIndex">
        <description>Add a Product to Solr Index (Note: mainly used internally)</description>
        <implements service="solrProductAttributes"/>
        <attribute mode="IN" name="fields" optional="true" type="Map">
            <description>A map of pre-formatted fields to add as-is to the solr document for indexing, with no field renaming or Solr type abstraction (added 2018-02-05)</description>
        </attribute>
        <attribute mode="IN" name="treatConnectErrorNonFatal" optional="true" type="Boolean" />
        <attribute mode="IN" name="useCache" optional="true" type="Boolean" default-value="false">
            <description>Use entity cache for extra lookups</description>
        </attribute>
        <attribute mode="IN" name="core" optional="true" type="String" />
        <attribute mode="OUT" name="errorType" optional="true" type="String" />
    </service>
    
    <service name="addListToSolrIndex" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="addListToSolrIndex">
        <description>Add a List of Products to Solr Index and flush after all have been added (Note: mainly used internally)</description>
        <attribute mode="IN" name="docList" optional="false" type="List" />
        <attribute mode="IN" name="treatConnectErrorNonFatal" optional="true" type="Boolean" />
        <attribute mode="IN" name="useCache" optional="true" type="Boolean" default-value="false">
            <description>Use entity cache for extra lookups</description>
        </attribute>
        <attribute mode="IN" name="core" optional="true" type="String" />
        <attribute mode="OUT" name="errorType" optional="true" type="String" />
    </service>

    <!-- ========================================================= -->
    <!-- Querying -->
    <!-- ========================================================= -->

    <service name="runSolrQuery" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="runSolrQuery">
        <description>Run a query on Solr and return the results</description>
        <attribute mode="IN" optional="false" name="query" type="String" allow-html="any"/>
        <attribute mode="IN" optional="true" name="start" type="Integer"/><!-- 2016-04-01: may specify either an absolute "start" value or a zero-based viewIndex -->
        <attribute mode="IN" optional="true" name="viewSize" type="Integer"/>
        <attribute mode="IN" optional="true" name="viewIndex" type="Integer"/>
        <attribute mode="IN" optional="true" name="queryFilter" type="String">
            <description>WARN: for legacy code reasons, this string is split on whitespace to produce multiple filters.
                    To avoid splitting, use queryFilters instead (with one entry).</description>
        </attribute>
        <attribute mode="IN" optional="true" name="queryFilters" type="List">
            <description>List of strings, each used as-is as a filter (no splitting).</description>
        </attribute>
        <attribute mode="IN" optional="true" name="sortByList" type="List">
            <description>List of strings, each optionally suffixed by " asc" or " desc"</description>
        </attribute>
        <attribute mode="IN" optional="true" name="sortBy" type="String"/>
        <attribute mode="IN" optional="true" name="sortByReverse" type="Boolean"/>
        <attribute mode="IN" optional="true" name="returnFields" type="String"/>
        <attribute mode="IN" optional="true" name="facetQuery" type="String"/>
        <attribute mode="IN" optional="true" name="facetQueryList" type="List"/>
        <attribute mode="IN" optional="true" name="facetFieldList" type="List"/>
        <attribute mode="IN" optional="true" name="facetMinCount" type="Integer"/>
        <attribute mode="IN" optional="true" name="facetLimit" type="Integer"/>
        <attribute mode="IN" optional="true" name="facet" type="Boolean">
            <description>DEPRECATED: 2019-08: this was a legacy parameter and you may simply omit it; default: false (changed 2017-09)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="highlight" type="Boolean"/><!-- default: false (REMOVED 2017-09: default-value="true") -->
        <attribute mode="IN" optional="true" name="spellcheck" type="Boolean"/><!-- default: false (REMOVED 2017-09: default-value="true") -->
        <attribute mode="IN" optional="true" name="spellDict" type="Object"/><!-- String or List -->
        <attribute mode="IN" optional="true" name="queryType" type="String">
            <description>Name of a request handler defined in solrconfig.xml (starts with /)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="defType" type="String">
            <description>Query language def handler type (dismax, edismax, ...), overrides the request handler</description>
        </attribute>
        <attribute mode="IN" optional="true" name="defaultOp" type="String">
            <description>OR or AND (default depends on configuration, usually OR); NOTE: Not honored by all defTypes (edismax supports)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="queryFields" type="String">
            <description>For edismax defType only: the target fields to query, usually space-separated ("qf" parameter)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="queryParams" type="Map">
            <description>Optional manual extra query options; NOTE: using above options is preferred when possible for better future-proofing of queries</description>
        </attribute>
        <attribute mode="IN" name="core" optional="true" type="String" />
        <attribute mode="IN" optional="true" name="solrUsername" type="String">
            <description>Username for Solr basic authentication (default: solrconfig.properties/solr.query.login.username)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="solrPassword" type="String">
            <description>Password for Solr basic authentication (default: solrconfig.properties/solr.query.login.password)</description>
        </attribute>
        <attribute mode="IN" name="lowercaseOperators" optional="true" type="Boolean">
            <description>For edismax: If true, "and" and "or" in queries are treated same as "AND" and "OR" (default: true in Scipio)</description>
        </attribute>
        <attribute name="queryResult" type="org.apache.solr.client.solrj.response.QueryResponse" mode="OUT" optional="true"/>
        <attribute name="errorType" type="String" mode="OUT" optional="true">
            <description>"query-syntax" for query syntax error, "general" otherwise (if error occurred) (added 2017-08-25)</description>
        </attribute>
        <attribute name="nestedErrorMessage" type="String" mode="OUT" optional="true">
            <description>Specific error message for the error, IF available (added 2017-08-25)</description>
        </attribute>
    </service>

    <service name="solrDefaultQueryFilters" engine="interface">
        <attribute mode="IN" name="core" optional="true" type="String" />
        <attribute mode="IN" optional="true" name="productStore" type="GenericValue"><!-- added 2018-05-25 -->
            <description>Product store (used to determine the product filtering defaults)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="useDefaultFilters" type="Boolean"><!-- added 2018-05-25 -->
            <description>If true, unless overridden with the explicit filter flags, the product stock and discontinuation filters 
                are applied based on the ProductStore configuration; if false, filters are not applied unless explicitly
                requested with the explicit filter flags (default: true)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="useStockFilter" type="Boolean"><!-- added 2018-05-25 -->
            <description>If true, filter out products with no inventory 
                (default: ProductStore.showOutOfStockProducts, or false)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="useDiscFilter" type="Boolean"><!-- added 2018-05-25 -->
            <description>If true, filter out products past their Product.salesDiscontinuationDate date 
                (default: ProductStore.showDiscontinuedProductsDefault, or false)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="excludeVariants" type="Boolean">
            <description>If true, exclude variant products
                (default: ProductStore.prodSearchExcludeVariants, or true)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="filterTimestamp" type="java.sql.Timestamp"/><!-- added 2018-05-25 -->
    </service>

    <service name="solrSearchCommon" engine="interface">
        <implements service="solrDefaultQueryFilters"/>
        <attribute mode="IN" name="core" optional="true" type="String" />
        <attribute mode="IN" optional="true" name="queryFilters" type="List">
            <description>List of strings, each used as-is as a filter (no splitting).</description>
        </attribute>
    </service>

    <service name="solrProductsSearch" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="solrProductsSearch">
        <description>Run a query on Solr and return the results</description>
        <implements service="solrSearchCommon"/>
        <attribute mode="IN" optional="false" name="productCategoryId" type="String"/>
        <attribute mode="IN" optional="true" name="includeSubCategories" type="Boolean">
            <description>default: true (legacy behavior)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="viewSize" type="Object">
            <description>Supports String, Integer (2017-09-11)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="viewIndex" type="Object">
            <description>Supports String, Integer (2017-09-11)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="sortByList" type="List">
            <description>List of strings, each optionally suffixed by " asc" or " desc"</description>
        </attribute>
        <attribute mode="IN" optional="true" name="sortBy" type="String"/>
        <attribute mode="IN" optional="true" name="sortByReverse" type="Boolean"/>
        <attribute mode="IN" optional="true" name="facetQuery" type="String"/>
        <attribute mode="IN" optional="true" name="facetQueryList" type="List"/>
        <attribute mode="IN" optional="true" name="facetFieldList" type="List"/>
        <attribute mode="IN" optional="true" name="facetMinCount" type="Integer"/>
        <attribute mode="IN" optional="true" name="facetLimit" type="Integer"/>
        <attribute mode="IN" optional="true" name="queryParams" type="Map">
            <description>Optional manual extra query options; NOTE: using above options is preferred when possible for better future-proofing of queries</description>
        </attribute>
        <attribute mode="IN" optional="true" name="facet" type="Boolean">
            <description>DEPRECATED: 2019-08: this was a legacy parameter and you may simply omit it; default: false (changed 2017-09)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="highlight" type="Boolean"/><!-- default: false -->
        <attribute mode="IN" optional="true" name="solrUsername" type="String">
            <description>Username for Solr basic authentication (default: solrconfig.properties/solr.query.login.username)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="solrPassword" type="String">
            <description>Password for Solr basic authentication (default: solrconfig.properties/solr.query.login.password)</description>
        </attribute>
        <attribute name="results" type="List" mode="OUT" optional="true"/>
        <attribute name="facetQueries" type="Map" mode="OUT" optional="true"/>
        <attribute name="facetFields" type="Map" mode="OUT" optional="true"/>
        <attribute name="start" type="Long" mode="OUT" optional="true"/>
        <attribute name="viewSize" type="Integer" mode="OUT" optional="true"/>
        <attribute name="viewIndex" type="Integer" mode="OUT" optional="true"/>
        <attribute name="listSize" type="Long" mode="OUT" optional="true"/>
        <attribute name="errorType" type="String" mode="OUT" optional="true">
            <description>"query-syntax" for query syntax error, "general" otherwise (if error occurred) (added 2017-08-25)</description>
        </attribute>
        <attribute name="nestedErrorMessage" type="String" mode="OUT" optional="true">
            <description>Specific error message for the error, IF available (added 2017-08-25)</description>
        </attribute>
    </service>

    <service name="solrKeywordSearch" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="solrKeywordSearch">
        <description>Run a query on Solr and return the results</description>
        <implements service="solrSearchCommon"/>
        <attribute mode="IN" optional="false" name="query" type="String" allow-html="any"/>
        <attribute mode="IN" optional="true" name="viewSize" type="Object">
            <description>Supports String or Integer (2017-09-11)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="viewIndex" type="Object">
            <description>Supports String or Integer (2017-09-11)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="queryFilter" type="String">
            <description>WARN: for legacy code reasons, this string is split on whitespace to produce multiple filters.
                    To avoid splitting, use queryFilters instead (with one entry).</description>
        </attribute>
        <attribute mode="IN" optional="true" name="sortByList" type="List">
            <description>List of strings, each optionally suffixed by " asc" or " desc"</description>
        </attribute>
        <attribute mode="IN" optional="true" name="sortBy" type="String"/>
        <attribute mode="IN" optional="true" name="sortByReverse" type="Boolean"/>
        <attribute mode="IN" optional="true" name="returnFields" type="String"/>
        <attribute mode="IN" optional="true" name="facetQuery" type="String"/>
        <attribute mode="IN" optional="true" name="facetQueryList" type="List"/>
        <attribute mode="IN" optional="true" name="facetFieldList" type="List"/>
        <attribute mode="IN" optional="true" name="facetMinCount" type="Integer"/>
        <attribute mode="IN" optional="true" name="facetLimit" type="Integer"/>
        <attribute mode="IN" optional="true" name="queryType" type="String">
            <description>Name of a request handler defined in solrconfig.xml (starts with /)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="defType" type="String">
            <description>Query language def handler type (dismax, edismax, ...), overrides the request handler</description>
        </attribute>
        <attribute mode="IN" optional="true" name="defaultOp" type="String">
            <description>OR or AND (default depends on configuration, usually OR); NOTE: Not honored by all defTypes (edismax supports)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="queryFields" type="String">
            <description>For edismax defType only: the target fields to query, usually space-separated ("qf" parameter)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="queryParams" type="Map">
            <description>Optional manual extra query options; NOTE: using above options is preferred when possible for better future-proofing of queries</description>
        </attribute>
        <attribute mode="IN" optional="true" name="facet" type="Boolean">
            <description>DEPRECATED: 2019-08: this was a legacy parameter and you may simply omit it; default: false (changed 2017-09)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="spellcheck" type="Boolean"/><!-- default: false (changed 2017-09) -->
        <attribute mode="IN" optional="true" name="spellDict" type="Object"/><!-- String or List -->
        <attribute mode="IN" optional="true" name="highlight" type="Boolean"/><!-- default: false (changed 2017-09) -->
        <attribute mode="IN" optional="true" name="solrUsername" type="String">
            <description>Username for Solr basic authentication (default: solrconfig.properties/solr.query.login.username)</description>
        </attribute>
        <attribute mode="IN" optional="true" name="solrPassword" type="String">
            <description>Password for Solr basic authentication (default: solrconfig.properties/solr.query.login.password)</description>
        </attribute>
        <attribute mode="IN" name="lowercaseOperators" optional="true" type="Boolean">
            <description>For edismax: If true, "and" and "or" in queries are treated same as "AND" and "OR" (default: true in Scipio)</description>
        </attribute>
        <attribute name="results" type="List" mode="OUT" optional="true"/>
        <attribute name="isCorrectlySpelled" type="Boolean" mode="OUT" optional="true">
            <description>Correctly-spelled flag - set if spellcheck was enabled
                WARN: May not behave as you might expect: https://issues.apache.org/jira/browse/SOLR-4278
                Can return false even if tokenSuggestions and fullSuggestions are empty</description>
        </attribute>
        <attribute name="facetQueries" type="Map" mode="OUT" optional="true"/>
        <attribute name="facetFields" type="Map" mode="OUT" optional="true"/>
        <attribute name="start" type="Long" mode="OUT" optional="true"/>
        <attribute name="viewSize" type="Integer" mode="OUT" optional="true"/>
        <attribute name="viewIndex" type="Integer" mode="OUT" optional="true"/>
        <attribute name="listSize" type="Long" mode="OUT" optional="true"/>
        <attribute name="queryTime" type="Long" mode="OUT" optional="true"/>
        <attribute name="suggestions" type="List" mode="OUT" optional="true"/><!-- DEPRECATED (2017-09-14): always returns null -->
        <attribute name="tokenSuggestions" type="Map" mode="OUT" optional="true">
            <description>Maps token to lists of suggestions - set if spellcheck was enabled (added 2017-09-14)</description>
        </attribute>
        <attribute name="fullSuggestions" type="List" mode="OUT" optional="true">
            <description>List of strings - spellcheck suggestions in collated format - set if spellcheck was enabled (added 2017-09-14)</description>
        </attribute>
        <attribute name="errorType" type="String" mode="OUT" optional="true">
            <description>"query-syntax" for query syntax error, "general" otherwise (if error occurred) (added 2017-08-25)</description>
        </attribute>
        <attribute name="nestedErrorMessage" type="String" mode="OUT" optional="true">
            <description>Specific error message for the error, IF available (added 2017-08-25)</description>
        </attribute>
    </service>
    
    <service name="solrAvailableCategories" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="solrAvailableCategories">
        <description>Run a query on Solr and return the results</description>
        <implements service="solrSearchCommon"/>
        <attribute mode="IN" optional="true" name="productCategoryId" type="String"/>
        <attribute mode="IN" optional="true" name="productId" type="String"/>
        <attribute mode="IN" optional="true" name="catalogId" type="String"/>
        <attribute mode="IN" optional="true" name="currentTrail" type="List"/>
        <attribute mode="IN" optional="true" name="displayProducts" type="Boolean"/>
        <attribute mode="IN" optional="true" name="viewSize" type="Integer"/>
        <attribute mode="IN" optional="true" name="viewIndex" type="Integer"/>
        <attribute name="numFound" type="Long" mode="OUT" optional="false"/>
        <attribute name="categories" type="java.util.Map" mode="OUT" optional="true"/>
    </service>
    
    <service name="solrAvailableCategoriesExtended" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="solrAvailableCategoriesExtended" >
        <description>Run a query on Solr and return the results in a more detailed way like solrSideDeepCategory</description>
        <implements service="solrAvailableCategories"/>
        <attribute mode="IN" optional="true" name="depth" type="String"/>
        <attribute name="categories" type="java.util.List" mode="OUT" optional="true"/>
        <attribute name="categoriesMap" type="java.util.Map" mode="OUT" optional="true"/>
    </service>
    
    <service name="solrSideDeepCategory" engine="java"
        transaction-timeout="72000"
        location="com.ilscipio.scipio.solr.SolrProductSearch"
        invoke="solrSideDeepCategory">
        <description>Run a query on Solr and return the results</description>
        <implements service="solrSearchCommon"/>
        <attribute mode="IN" optional="false" name="productCategoryId" type="String"/>
        <attribute mode="IN" optional="true" name="catalogId" type="String"/>
        <attribute mode="IN" optional="true" name="currentTrail" type="List"/>
        <attribute name="numFound" type="Long" mode="OUT" optional="false"/>
        <attribute name="categories" type="java.util.Map" mode="OUT" optional="true"/>
    </service>

    <service name="solrGetDoc" engine="java"
             transaction-timeout="72000"
             location="com.ilscipio.scipio.solr.SolrProductSearch"
             invoke="solrGetDoc">
        <description>Get document by ID</description>
        <implements service="solrSearchCommon"/>
        <attribute name="id" type="String" mode="IN" optional="false"/>
        <attribute name="doc" type="Map" mode="OUT" optional="true">
            <description>The first result</description>
        </attribute>
    </service>

    <service name="solrGetDocs" engine="java"
             transaction-timeout="72000"
             location="com.ilscipio.scipio.solr.SolrProductSearch"
             invoke="solrGetDocs">
        <description>Get documents by ID</description>
        <implements service="solrSearchCommon"/>
        <attribute name="idList" type="List" mode="IN" optional="true"/>
        <attribute name="resultType" type="String" mode="IN" optional="true" default-value="list">
            <description>Values: list, map</description>
        </attribute>
        <attribute name="docList" type="List" mode="OUT" optional="true">
            <description>Document list, if resultType list</description>
        </attribute>
        <attribute name="docMap" type="Map" mode="OUT" optional="true">
            <description>Maps id to document, if resultType map</description>
        </attribute>
    </service>
</services>