Where Can You Plug Them?
In the figure below, the icon indicates where you can plug custom processors:
Where Can You Plug Them?
In the figure below, the icon indicates where you can plug custom processors: Write Custom Query Processors
A query processor is the simplest component that you can write to customize query processing.
It takes the whole See Where Can You Plug Them? to know where you can add custom query processors. Write a Query Processor
Extend the Enable Your Custom Query ProcessorEdit the For example, to add a preparse processor,
edit the
LogicRunnerCustomization node of your SearchLogic as follows:
<s2:LogicRunnerCustomization> <s2:globalPreParseProcessors/> <s2:preParseProcessors> <s2:CustomProcessor classId="com.customer.processors.MyCustomProcessor"> <s2:KeyValue xmlns="exa:exa.bee" key="AConfigKey" value="A value" /> </s2:CustomProcessor> </s2:preParseProcessors> <s2:preLinguisticProcessors/> <s2:preTransformProcessors/> <s2:preMapProcessors/> <s2:postMapProcessors/> <s2:globalPostParseProcessors/> <s2:globalFinalProcessors/> </s2:LogicRunnerCustomization> Sample Custom Query ProcessorIn the sample below, a custom query processor refines the query by adding access restrictions. This query processor looks into the context (HTML parameter) and finds the profile value given by our custom UI. Depending on that value, the query processor expands the query with a specific prefix handler (perimeter) and the corresponding restricting value. You can plug this custom module at package com.exalead.customcode.search; import com.exalead.mercury.component.CVComponentDescription; import com.exalead.mercury.component.config.CVComponentConfig; import com.exalead.search.query.QueryContext; import com.exalead.search.query.QueryProcessingException; import com.exalead.search.query.node.Node; import com.exalead.search.query.node.NodeVisitor; import com.exalead.search.query.node.RootNode; import com.exalead.search.query.node.UserQueryString; import com.exalead.search.query.processors.CustomQueryProcessor; import com.exalead.search.query.processors.QueryProcessorContext; @CVComponentDescription("(Sample) Profile based query rewritting") public class ProfileBasedRestrictionQueryProcessor extends CustomQueryProcessor { public ProfileBasedRestrictionQueryProcessor(CVComponentConfig config) throws QueryProcessingException { super(config); } @Override public void onInit(QueryProcessorContext logic) { System.out.println("Connection to the profile DataBase onInit"); } @Override public void onDeinit(boolean allInstances) { System.out.println("Close the connection from the profile DataBase onDeinit"); } public boolean hasRestrictedAccess(String profileId){ if (profileId.equals("admin")){ return false; } return true; } @Override public void process(QueryContext context) throws QueryProcessingException { String profile = context.query.parameters.getParameterValue("profile"); if(profile != null){ if ( hasRestrictedAccess(profile) ){ context.currentNode = new RootNode(context.currentNode.accept(new MyQueryRewriter())); } } ; } static class MyQueryRewriter extends NodeVisitor { @Override public Node visit(UserQueryString queryString) { // add a prefix handler to restrict usage queryString.value += " perimeter:restrictive"; return queryString; } } } Write Custom Prefix Handlers
You can write your own prefix handlers to customize query processing. It takes the prefix handler value as input, and allows you to modify the context (including the AST in its current state). See Where Can You Plug Them? to know where you can add custom prefix handlers. Write a Prefix HandlerExtend the Create and Package Your Custom Prefix Handler
Sample Custom Prefix Handler
The Exalead CloudView default behavior is to use the You can replace the default A
package com.exalead.customcode.search; import com.exalead.config.bean.PropertyLabel; import com.exalead.mercury.component.CVComponent; import com.exalead.mercury.component.CVComponentDescription; import com.exalead.mercury.component.config.CVComponentConfigClass; import com.exalead.search.query.QueryContext; import com.exalead.search.query.QueryProcessingException; import com.exalead.search.query.node.And; import com.exalead.search.query.node.FuzzyAnd; import com.exalead.search.query.node.NaryNode; import com.exalead.search.query.node.Node; import com.exalead.search.query.node.NodeVisitor; import com.exalead.search.query.node.Or; import com.exalead.search.query.node.PrefixNode; import com.exalead.search.query.node.UserQueryChunk; import com.exalead.search.query.node.Xor; import com.exalead.search.query.prefix.CustomPrefixHandler; import com.exalead.search.query.util.NodeInspector; @PropertyLabel(value = "Change Behavior") @CVComponentConfigClass(configClass=ChangeDefaultBehaviorPrefixHandlerConfig.class) @CVComponentDescription("(Sample) This prefix handler allows to change the default behavior by using another operator rather than the default one.") public class ChangeDefaultBehaviorPrefixHandler extends CustomPrefixHandler implements CVComponent { private String operator = null; public ChangeDefaultBehaviorPrefixHandler(ChangeDefaultBehaviorPrefixHandlerConfig config) { super(config); operator = config.getOperator(); } public void addChildren(NaryNode newNode, String[] queryParts) { } @Override public Node handlePrefix(Phase phase, PrefixNode node, NodeVisitor parentVisitor, QueryContext queryContext) throws QueryProcessingException { if(phase.equals(Phase.PRE_LINGUISTIC)) { int slashPos = -1; String queryContent = NodeInspector.concatenatedContent(node).value; String[] queryParts = queryContent.split(" "); NaryNode newNode = null; if (operator.contains("XOR")) { newNode = new Xor(); } else if (operator.contains("OR")) { newNode = new Or(); } else if (operator.contains("FUZZYAND")) { newNode = new FuzzyAnd(); slashPos = operator.indexOf("/"); if (slashPos < 0){ ((FuzzyAnd)newNode).minSuccess = (int)queryParts.length / 2; } else if (operator.charAt(slashPos + 1)== '-'){ ((FuzzyAnd)newNode).maxFailure= new Integer(operator.substring(slashPos + 2)); } else { ((FuzzyAnd)newNode).minSuccess= new Integer(operator.substring(slashPos + 1)); } } else { newNode = new And(); } for (int i = 1; i < queryParts.length; i++){ newNode.addChild(new UserQueryChunk(queryParts[i])); } if (parentVisitor != null) { return newNode.accept(parentVisitor); } return newNode; } if (parentVisitor !=null) { node.setContent(node.getContent().accept(parentVisitor)); } return node; } } |