I just wrote a custom CharTokenizer, and I want to use it in my Solr server.
In Solr3, I could just extend TokenizerFactory and return my CharTokenizer in the create method, but TokenizerFactory does not exist in Solr4.
So, I was noticed that I should replace TokenizerFactory with TokenFilterFactory, but in this case, I cannot return my custom CharTokenizer, because the parameters don't match.
I also search for some documentation, but looks like there is nothing really useful about that out there.
So, how can I make it works?
Example:
public class MyCustomTokenizer extends CharTokenizer {
char anotherSpace = 24;
public MyCustomTokenizer(Version matchVersion, Reader in) {
super(matchVersion, in);
}
protected boolean isTokenChar(int c) {
return !Character.isWhitespace(c) && isToken((char) c);
}
private boolean isToken(char c) {
if (c == anotherSpace || c == ',') {
return false;
}
return true;
}
}
public class MyCustomTokenizerFactory extends TokenFilterFactory {
public void init(Map<String, String> args) {
super.init(args);
assureMatchVersion();
}
#Override
public TokenStream create(TokenStream input) {
// sh*t happens here
return new MyCustomTokenizer(luceneMatchVersion, input);
}
}
Thanks in advance.
The best way to check for implementation is looking the Source code of an existing Tokenizer in Lucene.
Example :-
WhitespaceTokenizer
WhitespaceTokenizerFactory
Related
I am trying to refactor old SimpleFormController. I would like to replace getSuccessView() and gerFormView() calls with actual success view and form view Strings.
I went through https://spoon.gforge.inria.fr/first_transformation.html, it shows how to generate and add statements however I could not understand how to modify.
I have tried couple of things.
Replace statements with the getSuccessView() and getFormView() calls
public class SimpleFormControllerReplaceViewCall extends AbstractProcessor<CtMethod> {
MetaData meta;
String successView= "successView";
String formView = "formView";
public SimpleFormControllerReplaceViewCall(MetaData meta) {
this.meta = meta;
}
#Override
public boolean isToBeProcessed(CtMethod candidate) {
if(candidate.getBody() == null) { //Ignore abstract methods
return false;
}
String sourceCode;
try {
sourceCode = candidate.getBody()
.getOriginalSourceFragment()
.getSourceCode();
} catch (Exception e) {
return false;
}
return sourceCode.contains(getViewFunctionName(successView))
|| sourceCode.contains(getViewFunctionName(formView));
}
#Override
public void process(CtMethod method) {
Node beanNode = getBeanNode(method);
CtBlock<Object> body = getFactory().createBlock();
method.getBody().getStatements()
.stream()
.map(s -> {
Optional<String> sourceCode = getStatementSourceCode(s);
if(!sourceCode.isPresent()) {
return s.clone(); // Clone required to handle runtime error for trying attach a node to two parents
} else {
System.out.println("Modifying: " + method.getSignature());
String code = sourceCode.get();
code = replaceViewCalls(beanNode, code, successView);
code = replaceViewCalls(beanNode, code, formView);
return getFactory().createCodeSnippetStatement(code);
}
}).forEach(body::addStatement);
method.setBody(body);
}
private Optional<String> getStatementSourceCode(CtStatement s) {
String sourceCode = null;
try {
sourceCode = s.getOriginalSourceFragment()
.getSourceCode();
} catch (Exception e) {}
System.out.println(sourceCode);
if (sourceCode != null &&
(sourceCode.contains(getViewFunctionName(successView))
|| sourceCode.contains(getViewFunctionName(formView)))) {
sourceCode = sourceCode.trim();
if(sourceCode.endsWith(";"))
sourceCode = sourceCode.substring(0, sourceCode.length()-1);
return Optional.of(sourceCode);
} else {
return Optional.empty();
}
}
public String replaceViewCalls(Node beanNode, String code, String viewType) {
String getViewFunctionName = getViewFunctionName(viewType);
if (!code.contains(getViewFunctionName)) {
return code;
}
String view = AppUtil.getSpringBeanPropertyValue(beanNode, viewType);
return code.replaceAll(getViewFunctionName + "\\(\\)", String.format("\"%s\"", view));
}
public Node getBeanNode(CtMethod method) {
String qualifiedName = method.getParent(CtClass.class).getQualifiedName();
return meta.getFullyQualifiedNameToNodeMap().get(qualifiedName);
}
private String getViewFunctionName(String viewType) {
return "get" + viewType.substring(0, 1).toUpperCase() + viewType.substring(1);
}
}
This however adds unwanted at end of blocks if() {... }; This creates syntax errors when if {} else {} blocks contain return statement(s). Auto import is turned on and imports are not added when there is more one class with same name (e.g., Map is present in classpath from few libraries) - this is consistent with the document. Can this be avoided when refactoring code? Original java file has correct imports.
Another approach I tried is to directly manipulate the body as a whole.
#Override
public void process(CtMethod method) {
String code = method.getBody()
.getOriginalSourceFragment()
.getSourceCode();
Node beanNode = getBeanNode(method);
code = replaceViewCalls(beanNode, code, successView);
code = replaceViewCalls(beanNode, code, formView);
CtCodeSnippetStatement codeStatement = getFactory().createCodeSnippetStatement(code);
method.setBody(codeStatement);
}
this still has same auto import issue as first one. Apart from that it adds redundant curly braces, for examples
void method() { x=y;}
will become
void method() { {x=y;} }
That that will be pretty printed ofcourse.
Also javadocs for getOriginalSourceFragment() also has below warning
Warning: this is a advanced method which cannot be considered as part
of the stable API
One more thing I thought of doing is creating pattern for each type of usage of getSuccessView() like
viewName = getSuccessView();
return getSuccessView();
return ModelAndView(getSuccessView(), map); etc, however for that I will have to write a whole bunch of processors / templates.
Since it is simple replacement, easiest is do something like below
//Walk over all files and execute
Files.lines(Paths.get("/path/to/java/file"))
.map(l -> l.replaceAll("getSuccessView\\(\\)", "actualViewNameWithEscapedQuotes"))
.map(l -> l.replaceAll("getFormView\\(\\)", "actualViewNameWithEscapedQuotes"))
.forEach(l -> {
//write to file
});
Since I can avoid text manipulation with the help of spoon for things like changing modifiers, annotations, method name, annotations etc, I am hoping there should be a better way to modify the method body.
You should treat the processor input as an abstract syntax tree instead of a string:
public class SimpleFormControllerReplaceViewCall extends AbstractProcessor<CtMethod<?>> {
#Override
public boolean isToBeProcessed(CtMethod candidate) {
if(candidate.isAbstract()) { //Ignore abstract methods
return false;
}
return !candidate.filterChildren((CtInvocation i)->
i.getExecutable().getSimpleName().equals("getSuccessView")
|| i.getExecutable().getSimpleName().equals("getFormView")).list().isEmpty();
}
#Override
public void process(CtMethod<?> ctMethod) {
Launcher launcher = new Launcher();
CodeFactory factory = launcher.createFactory().Code();
List<CtInvocation> invocations = ctMethod.filterChildren((CtInvocation i)->
i.getExecutable().getSimpleName().equals("getSuccessView")
|| i.getExecutable().getSimpleName().equals("getFormView")).list();
for(CtInvocation i : invocations) {
if(i.getExecutable().getSimpleName().equals("getSuccessView")) {
i.replace(factory.createLiteral("successView"));
} else {
i.replace(factory.createLiteral("formView"));
}
}
}
}
Here the CtMethod AST is traversed in search for CtInvocation elements with the specified properties. The found elements are then replaced with new string literal elements.
I wanted to know if is it possible to have a method that can choose between multiple classes and return one of them.
This is what it should look like:
public class BotManager {
public static Test test;
public static int PROTOCOL_VERSION = 114;
public Bot bot(){
if(PROTOCOL_VERSION == 114){
return test.bot114;
}else{
return test.bot111;
}
}
in this example, bot111 and bot114 are different classes.
bot.version111.bot.Bot;
bot.version114.bot.Bot;
Yeah of course you can.
You just need to be sure that bot114 and bot111 both extend the Bot class.
For these purposes you would use what's called a factory, here is an example of a factory that returns different Windows based on the Class type:
public static Window getCsvExportWindow(Class tab) {
if (tab == OnhandTab.class) {
return new OnhandCsvExportWindow();
} else {
return new CustOrderCsvExportWindow();
}
}
Instead of Class type you use your PROTOCOL_VERSION.
You can use it's code:
if (Object object instanceof Bot114) {
return new Bot114();
} else if (Object object instanceof Bot111) {
return new Bot111();
} else {
return null;
}
I created a factory pattern in my class.
In this class I injected classes which implements Command interface based on incoming String parameter.
Factory class
#Component
#RequiredArgsConstructor
public class CommandFactory {
private final ACommand aCommand;
private final BCommand bCommand;
private final CCommand cCommand;
private final DCommand dCommand;
private final ECommand eCommand;
private final FCommand fCommand;
public Command createCommand(String content) {
if (aCommand.isMatching(content)) {
return aCommand;
} else if (bCommand.isMatching(content)) {
return bCommand;
} else if (cCommand.isMatching(content)) {
return cCommand;
} else if (dCommand.isMatching(content)) {
return dCommand;
} else if (eCommand.isMatching(content)) {
return eCommand;
} else if (fCommand.isMatching(content)) {
return fCommand;
} else {
return null;
}
}
In isMatching() method there are different regex'es and I try to figure out how this incoming String should be processed.
I am looking for a cleaner way to get rid of these sequential if statements. Because whenever I create a new class into this factory I add another if statement.
Maybe Stream can help?
Stream<Command> stream = Stream.of(aCommand, bCommand, cCommand ...);
return stream.filter(x -> x.isMatching(content)).findFirst().orElse(null);
Now every time you add a new class, you just add a new object to the first line.
If you want to get rid of the sequential if statements you can use streams (like user Sweeper suggested) or loops and I would also suggest to return and optional which makes null handling clearer for the client.
Here are two suggested options to get rid of if else repetitions one with loops another with streams:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class CommandPatternExample {
private List<Command> candidates = Arrays.asList(new ACommand(), new BCommand(), new CCommand());
public Optional<Command> createCommand(String content) {
for(Command command : candidates) {
if(command.isMatching(content)) {
return Optional.of(command);
}
}
return Optional.empty();
}
public Optional<Command> createCommandStream(String content) {
return candidates.stream().filter(c -> c.isMatching(content)).findFirst();
}
}
interface Command<T> {
void execute(T obj);
boolean isMatching(String s);
}
class ACommand implements Command<String> {
#Override
public void execute(String obj) {
}
#Override
public boolean isMatching(String s) {
return "A".equals(s);
}
}
class BCommand implements Command<String> {
#Override
public void execute(String obj) {
}
#Override
public boolean isMatching(String s) {
return "B".equals(s);
}
}
class CCommand implements Command<String> {
#Override
public void execute(String obj) {
}
#Override
public boolean isMatching(String s) {
return "C".equals(s);
}
}
Map might be a good idea. Meaning if you place your command instances into a map as values where your key would be something that you could match against incoming String. Then instead of sequential search with Efficiency O(n) you can get much better performance O(1). This is a short answer.
Besides that There is an open source java library MgntUtils (wriiten by me) that contains some utility called "Self-instantiating factories" Basically it manages and the Factory for you. All you will need to do is to create a class that implements a certain interface and the utility will add it for you into a map based factory. It might be useful to you. Here is the link to an article that explains about the utilities in the library as well as where to get the library (Github and Maven central). In the article look for the paragraph "Lifecycle management (Self-instantiating factories)". Also library comes with a detailed written javadoc and code example for that feature.
I got a big problem to deal with, my code is too long and full characters. I removed a lot, using methods and using some proper design patterns... But it is still too "crowded".
I get a string from the user, a question like:
"How are you Josh?"
"Who is Josh's mother?"
I need to analyze that question so see it's content and to System.out.print() the answer.
so a long serie of "if/else if" starts e.g
if (question.startsWith("How") && question.endsWith("Josh?"))
{
//do a lot of things here.
System.out.print(actualHealth);
}
else if (question.startsWith("Who") && question.endsWith("mother?"))
{
//do a lot of things here.
System.out.print(getParents().getMother());
}
*
*
* //Lot of "else if" here to recognize the question meaning.
*
*
else
{
System.out.print("question not recognized");
}
I called this class AnswersFactory as referred to the Design Pattern "Factory Pattern" because the question, is "asked" in another class. But I suppose it's a wrong way to consider it a design pattern.
How to simplify all those conditions even if they seem impossible to simplify, or at least make the code seem more organized? Is there a good design pattern to follow?
My code works great but is not beautiful to see. I hope you understand that frustration!
Thank you.
Not sure why you want to check the question based on the keyword, it has some drawbacks like mentioned by HCBPshenanigans
But to change it to be more flexible, I would do something like this:
An interface for all question handlers
public interface IQuestionHandler
{
bool CanHandle(string question);
void Handle(string question);
}
Concrete class for each scenario. Each class will tell whether it can handle the question or not, and contain logic to handle the question:
public class HealthQuestionHandler : IQuestionHandler
{
public bool CanHandle(string question)
{
return question.StartsWith("How") && question.EndsWith("Josh?");
}
public void Handle(string question)
{
//Replace by actual processing
string healthStatus = "I'm fine";
Console.WriteLine(healthStatus);
}
}
public class MotherQuestionHandler : IQuestionHandler
{
public bool CanHandle(string question)
{
return question.StartsWith("Who") && question.EndsWith("mother?");
}
public void Handle(string question)
{
//Replace by actual processing
string mother = "...";
Console.WriteLine(mother);
}
}
And finally a question handler processor to manage all the handlers. It will register all available handlers in constructor. When called to process, it goes through all of available handlers, ask one by one which one can handle the question
public class QuestionHandlerProcessor
{
private List<IQuestionHandler> _handlers;
public QuestionHandlerProcessor()
{
//Register available handlers
_handlers = new List<IQuestionHandler>
{
new HealthQuestionHandler(),
new MotherQuestionHandler()
};
}
public void Process(string question)
{
foreach(var handler in _handlers)
{
if(handler.CanHandle(question))
{
handler.Handle(question);
return;
}
}
Console.WriteLine("Question not recognized");
}
}
Usage:
QuestionHandlerProcessor processor = new QuestionHandlerProcessor();
processor.Process("How are you Josh?");
processor.Process("Who is Josh's mother?");
Although my answer is in C#, but should not be difficult to convert to Java.
you can use Chain Of Responsibility pattern. you will need catching the exception
UnhandledQuestionException
.
public abstract class QuestionHandler {
protected QuestionHandler successor;
public void setSuccessor(QuestionHandler successor) {
this.successor = successor;
}
public abstract void handle(String question);
}
and implementors should be so
public class HealthQuestionHandler extends QuestionHandler {
private bool canHandle(String question) {
return question.startsWith("How") && question.endsWith("Josh");
}
public void handle(String question) {
if( canHandle(question) ) {
String healthStatus = "I am fine";
System.out.println(healthStatus);
} else {
super.successor.handle(question);
}
}
}
public class MotherQuestionHandler extends QuestionHandler {
private bool canHandle(String question) {
return question.startsWith("Who") && question.endsWith("Mother");
}
public void handle(String question) {
if( canHandle(question) ) {
String mother = "..."; //name
System.out.println(mother);
} else {
super.successor.handle(question);
}
}
}
the final handler, when question cannot be handled:
public class UnhandledQuestionHandler extends QuestionHandler {
public void handle(String question) {
throw new UnhandledQuestionException("question not recognized");
}
}
you should create
UnhandledQuestionException
first, that extends Exception class.
you should create QuestionHandlerFactory too.
public class QuestionHandlerFactory {
public static QuestionHandler create() {
//if you can have several variants of this handler combinations, this method shouldn't be static
QuestionHandler healthQuestionHandler = new HealthQuestionHandler();
QuestionHandler motherQuestionHandler = new MotherQuestionHandler();
QuestionHandler unhandledQuestionHandler = new UnhandledQuestionHandler()'
motherQuestionHandler.setSuccessor(unhandledQuestionHandler);
healthQuestionHandler.setSuccessor(motherQuestionHandler);
return healthQuestionHandler;
}
}
and in the user of this class will be:
QuestionHandler handler = QuestionHandlerFactory.create();
try {
handler.handle(question);
} catch( UnhandledQuestionException ex ) {
System.out.println(ex.getMessage());
}
create an enum for your Constants such "WHO","HOW", .... and WHERE" then try to use switch after that
you can create enum in the same class
You can use Factory pattern and a strategy pattern. Since Qestion is being asked in a different class (let's call it QueryResolver ) it should look like this :
class QueryProcessor
{
private IQueryResolver _ resolver;
//We will be injecting our dependencies in the constructor (Dependency Inversion)
public QueryProcessor(IQueryResolver resolver )
{
_resolver = resolver;
}
public string ProcessQuery()
{
_resolver.ResolveQuery();
}
Now your QueryResolver Implements the IQueryResolver interface
public interface IQueryResover
{
string ResolveQuery();
}
And you will have multiple implementation of IQueryResolver each responsible for a particular kind of Query e.g.:
//This particular implementation know how to resolve question including the "Who" key word.
class WhoQueryResolver : IQueryResolver
{
private string _question;
public WhoQueryResolver(string question)
{
_question = question;
}
public string ResolveQuery()
{
//do a lot of things here.
System.out.print(getParents().getMother());
}
Similarly,
class HowQueryResolver : IQueryResolver
{
private string _question;
public HowQueryResolver(string question)
{
_question = question;
}
public string ResolveQuery()
{
//do a lot of things here.
System.out.print(GetActualHealth());
}
than finally a factory which return concrete implementation of IQueryResolver
public class QueryResolverFactory
{
public static IQueryResolver GetQueryResolver()
{
if (question.startsWith("How") && question.endsWith("Josh?"))
{
return new HowQueryResolver(question);
}
else if (question.startsWith("Who") && question.endsWith("mother?"))
{
return new WhoQueryResolver(question);
}
}
}
I want to design API which could handle XPATH input from user.
Currently i have model the XPATH input in following way,
public interface ICondition {
String getConditionString();
}
public class XPathCondition implements ICondition {
private Class<? extends XPATHFunction> clazz = null;
private Operator operator = null;
private String compValue = null;
private String param = null;
public void setXPathFunction(Class<? extends XPATHFunction> clazz) {
this.clazz = clazz;
}
public void setComparisionType(Operator operator) {
this.operator = operator;
}
public void setComparisionValue(String value) {
this.compValue = value;
}
public void setParam(String param) {
this.param = param;
}
public String getConditionString() {
XPATHFunction function = null;
try {
function = (XPATHFunction) clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return function.call(param) + operator.getOprValue() + compValue;
}
public static void main(String[] args) {
XPathCondition xpathCond = new XPathCondition();
xpathCond.setXPathFunction(CountFunction.class);
xpathCond.setParam("/CPRRegistrationInfo/*");
xpathCond.setComparisionType(Operator.GT);
xpathCond.setComparisionValue("0");
System.out.println(xpathCond.getConditionString());
}
}
public interface XPATHFunction {
public String call(String param);
}
public class CountFunction implements XPATHFunction {
public String call(String param) {
return "count(" + param + ") ";
}
}
There could be other XPATH function which have to implement and interface XPATHFunction and implement it in its way.
API just have create XPATHCondition and set appropriate function and call getConditionString() method to get the final xpath.
Is there any better way, we can model XPATH input?
Please help me to re factor the above design.
I don't think I cannot really comment on your class structure or suggest something different. It is a very tough problem.
What I'd suggest is:
Start with some simple sub-set of the full XPath syntax
Instead of starting from the design of the API and the classes start designing the user interface: what are you going to show the user? What are his/her possible actions? The class design should then derive from the UI design.
If possible use a schema for the underlying XML, so that you can present the user with a limited choice of the possible element and attribute name to use in the expression