ElasticSearch 5 adding context to SuggestionBuilders - java

I am working on ES5 through java, and am trying to add context to a CompletionSuggestionBuilder. I have a map of String objects that need to be added. The code I have so far is -
Map<String, String> context = ...
CompletionSuggestionBuilder csb = SuggestBuilders.completionSuggestion(field).text(value).size(count);
How do I add context objects to csb? I think the method to use is -
csb.contexts(Map<String, List<? extends ToXContent>> queryContexts)
But I don't know how to get from my map to the map to pass as arguments to the contexts method.

You can create Map<String, List<? extends ToXContent>> like this;
Collections.singletonMap("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build()))
I think currently supported types that extend ToXContext are CategoryQueryContext and GeoQueryContext
The strange thing here is that if I create a local variable and pass it to the contexts it does not work. So, I just passed it directly to the contexts it does work.
Full example would be like this:
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg").contexts(Collections.singletonMap("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build())));
It is all written in their test cases. You can take a look at it:
https://github.com/elastic/elasticsearch/blob/master/core/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java#L290
Hope it helps.

Related

Init Generic Class Using Reflection Java

I am currently automating a process of a data handler. What I mean with automating is that the DataHandlers are initiated automatically via reflection based on a specific configuration.
But I am on a point where I do not know how I should solve this problem. It is about this peace of code:
Class<?> clazz = classLoader.loadClass(d);
Object values = clazz.getMethod("values").invoke(null);
RSA.addDataHandler(clazz,new DataHandlerSetAdapter<>(values));
I am loading the class via the classLoader and invoking a static method called "values" which returned a bunch of, you have suggested right, values!
Now the problem is with new DataHandlerSetAdapter<>(values)) which has an error in <> because the Object does not know which class to initiate.
Cannot infer arguments (unable to resolve constructor)
Would this code be in C# I would use typeof() but in JAVA there is nothing like this maybe instanceof but I cannot use this at this point. Btw .values() is returning an Array of the same type class (enum).
How can I solve this problem?
//edit
with the method .getReturnType() on the Method I would get the return type but I cannot apply it to the DataHandlerSetAdapter<>
Class DataHandlerSetAdapter
public class DataHandlerSetAdapter<T> implements DataHandler<T> {
private final Set<T> values = new ConcurrentSkipListSet<>();
.
.
.
}
It is not clear to me what you are trying to do. But if the loadable class is an enum, then why you are not doing it like this:
Class<? extends Enum<?>> clazz = classLoader.loadClass(d);
Enum<?>[] values = clazz.getEnumConstants();
RSA.addDataHandler(clazz, new DataHandlerSetAdapter<>(values));
Alternatively you can use raw types:
RSA.addDataHandler(clazz, new DataHandlerSetAdapter(values)) - note no diamonds <>.
But Still I'm not sure weather will this work for you or not. Please provide the following information to understand the root cause of failure.
Signature of DataHandlerSetAdapter constructor
Signature of RSA.addDataHandler(...) method
More info about RSA you used in your code snippet. (e.g. Is it a class or object)

Injecting list of strings in Guice

I am trying to inject one arraylist of Strings in Guice. For that I am trying to construct list as following in module, which I can inject later into any class:
Multibinder<String> myList =
Multibinder.newSetBinder(binder(), String.class);
myList.addBinding().to("Test1");
myList.addBinding().to("Test2");
In the above line I am getting following error:
The method to(Class<? extends String>) in the type LinkedBindingBuilder<String> is not applicable for the arguments (String)
In this context, I have found this: Guice : Inject an ArrayList of Strings, but I think given solution does not fit my use case.
Use .toInstance()
myList.addBinding().toInstance("Test1");
myList.addBinding().toInstance("Test2");`
I realize this is an older post, but I've been unsuccessful at finding a solution until today. I've wanted to inject a list of comma-delimited strings defined in a property file in a generic way without having to explicitly create #Named providers for every property that needed to be represented as a list of Strings.
Today I found this post (Injecting a List of Strings From a Properties File Using Guice). The relevant part for me was this line in my configure method:
#Override
protected void configure() {
...
binder().convertToTypes(Matchers.only(new TypeLiteral<List<String>>() {
}), (String value, TypeLiteral<?> toType) -> Arrays.asList(value.split(",")));
...
}
I didn't use DefaultListDelimiterHandler as the original solution did, but instead just did a standard string split converted to a List. Now from a property file, I can have something like:
testList=one,two,three
And I can inject it using:
#Inject
#Named("testList")
List<String> testList;

How can I create an instance from a own class in FreeMarker (FTL)

I wish to instantiate a java class that I have defined in my domain and I want to use it from my FTL code in this way, but I'm getting an error.
<#assign myClassInstance = "com.domain.MyClass"?new())>
Is it possible? What I should change to do it?
MyClass doesn't implements the TemplateModel
Thanks!
There's no built-in function for instantiating arbitrary non-TemplateModel classes... maybe there should be a setting to allow that for ?new. Anyway, for now you can write a TemplateMethodModelEx that does that, and then you can pull that into some of your commonly included/imported templates like <#assign unrestrictedNew = "com.example.UnrestrictedNewMethodModel"?new()> (or just put the instance into the data-model or into the Configuration as a shared variable) and then you can do <#assign myClassInstance = unrestrictedNew("com.domain.MyClass")(arg1, arg2, argN)> in your templates. There are two tricky parts in implementing such a TemplateMethodModel. One is resolving the class name to a Class, for which I recommend env.getNewBuiltinClassResolver().resolve(className, env, null), where env is the current freemarker.core.Environment object. The other is calling the constructor, as then you have to convert parameter values and possibly chose an overloaded constructor. For that I recommend calling ow = env.getObjectWrapper(), see if ow instanceof BeansWrapper (throw exception if it isn't), then do return ((BeansWrapper) ow).newInstance(cl, arguments).

Best way to pass arguments in constructor

I have a class that create rows in table layout. The row creation depend upon data and metadata. As metadata is same for each row like show/hide visibility properties etc. so I have created metadata property as a static and initialize once using initWidget of RowWidget.
just example:
class RowWidget extends FlexTable{
public static void initWidget(Form form,
HashMap<Long, ContractorPermissionEnum> formModePermissionMap,
GridMode gridMode,
boolean isApplied,
boolean isChildExist,
boolean isChildAttachment)
{
// ...
}
}
Then I called below constructor for each record data.
public RowWidget(DataRawType dataRawType, Data data, Data parentData) {
// ...
}
As I thought this is not right approach. because as pattern when anyone see this class then understand it will create one row. I don't want to call initially initWidget. I want to pass each required parameter in constructor only like
public RowWidget(DataRawType dataRawType,
Data data,
Data parentData,
Form form,
HashMap<Long, ContractorPermissionEnum> formModePermissionMap,
GridMode gridMode,
boolean isApplied,
boolean isChildExist,
boolean isChildAttachment) {
// ...
}
But due to this, constructor have no of arguments. and I think it's also bad pattern to have 5+ parameter in constructor.
Is Anyone suggest me:
How to construct class which have same property required in another
instance?
Note:I know this is possible through static only but don't want to use static.
What is best way to construct class with having some default fix
property for all instances?
Note: I don't want to create another class to achieve it. or any getter/setter method.
Thanks In advance.
I would suggest builder pattern. You would need one extra class to create RowWidget objects. So the call would look like that:
RowWidget widget = new RowWidget.Builder().withData(data).withParentData(parentData).withDataRawType(dataRawType).build();
Here is neat explanation of the pattern:https://stackoverflow.com/a/1953567/991164
Why not create method which will accept the newValues for the properties you want to change & return a new instance of the classes with all other properties copied from the instance on which you invoked this method.
You could separate/extract the parameters from the RowWidget-class fro example in a RowWidgetConfig-class.
class RowWidgetConfig {
// put here all your parameters that you need to initialize only once
// init using setters
}
Now create once instance of that class and pass it among the other parameters to RowWidget constructor.
Another alternative would be to have factory for creating RowWidget instances. The factory would also contain all the parameters you need for a row instance plus a factory method createNewRowWidget witch creates an instance base on the parameters contained in the factory.
class RowWidgetFactory {
// put here all your parameters that you need to initialize only once
// init using setters
public RowWidget createNewRowWidget() {
// create
return ...
}
}
How to construct class which have same property required in another instance?
To achive this you can have a super class with all the properties you want. So any class extending this super class will be have these properties. This way you don't need to use static keyword.
What is best way to construct class with having some default fix property for all instances?
For this one you can have an interface with some constant properties. This way any class implementing this interface will be having the fixed properties.
The static initWidget() thing just doesn't seem right for me. Though probably now you will only have one set of RowWidgets which share some properties, it is also reasonable to have 2 sets of RowWidgets, each set will have its own "shared" properties. Things will be much more fluent and you have much more choices in building more reasonable APIs if you refactor your code to make a more reasonable design
Assume now I introduce something like a RowGroup (which kind of represents the "shared" thing you mentioned)
(Honestly I don't quite get the meaning for your design, I am just making it up base on your code);
public class RowGroup {
public RowGroup(Form form,
HashMap<Long, ContractorPermissionEnum> formModePermissionMap,
GridMode gridMode,
boolean isApplied,
boolean isChildExist,
boolean isChildAttachment) { .... }
public void addRow(DataRawType dataRawType, Data data, Data parentData) {...}
}
When people use, it looks something like:
RowGroup rowGroup = new RowGroup(form, permissionMap, gridMode, isApplied, isChildExist, isChildAttach);
rowGroup.addRow(DataRawType.A, dataA, parentA);
rowGroup.addRow(DataRawType.B, dataB, parentB);
You may even provide builder-like syntax or a lot other choices.
RowGroup rowGroup
= new RowGroup(.....)
.addRow(DataRawType.A, dataA, parentA)
.addRow(DataRawType.B, dataB, parentB);
Even more important, the design now make more sense to me.
If you did not want to create another class, I'd suggest what A4L suggested.
Without creating another class, I would create constructor that takes all parameters and factory method that uses current instance as template and pass its own parameters to constructor parameter.
example (with obvious parts ommited)
class A{
public A(int p1, int p2){...}
public A create(int p2) {
return new A(this.p1,p2);
}

Putting classes in a Hashtable

I have a set of classes that implement a certain interface. I have put all those classes in a Hashtable ht like this:
ht.put(str,backend.instructions.ADC.class);
But when I call the get() function of the hashtable and try to cast the object as the Interface's object, I am getting a ClassCastException:
InsInterface4 obj=(InsInterface4) ht.get(str);
How can I resolve the same? I have to call functions of the class but, I am not even able to cast properly? What is wrong in this?
Because you are putting a Class and you try to get an Interface4. If you want to have instances, rather than definitions inside the map, use: t.put(str, new ADC()). A few notes:
You can also use generics to guarantee that you put the correct things at compile time: Hashtable<String, Interface4>.
Prefer HashMap to Hashtable
backend.instructions.ADC.class is a Class, not an instance of that class.
You can do
Class<InsInterface4> clazz = (Class<InsInterface4>) ht.get(str);
// if there is a default constructor
InsInterface4 obj = (InsInterface4_ clazz.newInstance();
You have put the definition of the class in the table. You need to put actual instances of the class.
backend.instructions.ADC anAdc = new backend.instructions.ADC();
someOther.instructions.OTH anOth = new someOther.instructions.OTH();
ht.put("adc", anAdc);
ht.put("oth", anOth);
InsInterface4 obj=(InsInterface4) ht.get("adc");

Categories

Resources