#FacesValidator("uniqueValidator")
public class UniqueValidator implements Validator
{
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
{
if(context == null)
{
throw new NullPointerException();
}
if(component == null)
{
throw new NullPointerException();
}
ValueExpression valueExpression = component.getValueExpression("value");
if(valueExpression == null)
{
return;
}
ValueReference valueReference = valueExpression.getValueReference(context.getELContext());
if(valueReference == null)
{
return;
}
Object base = valueReference.getBase();
Object property = valueReference.getProperty();
Tracer.out(base, property);
.....
}
}
and ValueReference is always null.
what's wrong?
thank you BeanValidator :)
public class ValueExpressionAnalyzer
{
public static ValueReference getReference(ELContext elContext, ValueExpression expression)
{
InterceptingResolver resolver = new InterceptingResolver(elContext.getELResolver());
try
{
expression.setValue(new InterceptingContext(elContext, resolver), null);
}
catch(ELException ele)
{
return null;
}
ValueReference reference = resolver.getValueReference();
if(reference != null)
{
Object base = reference.getBase();
if(base instanceof CompositeComponentExpressionHolder)
{
ValueExpression ve = ((CompositeComponentExpressionHolder) base).getExpression((String) reference.getProperty());
if(ve != null)
{
reference = getReference(elContext, ve);
}
}
}
return reference;
}
private static class InterceptingContext extends ELContext
{
private final ELContext context;
private final ELResolver resolver;
public InterceptingContext(ELContext context, ELResolver resolver)
{
this.context = context;
this.resolver = resolver;
}
// punch in our new ELResolver
#Override
public ELResolver getELResolver()
{
return resolver;
}
// The rest of the methods simply delegate to the existing context
#Override
public Object getContext(Class key)
{
return context.getContext(key);
}
#Override
public Locale getLocale()
{
return context.getLocale();
}
#Override
public boolean isPropertyResolved()
{
return context.isPropertyResolved();
}
#Override
public void putContext(Class key, Object contextObject)
{
context.putContext(key, contextObject);
}
#Override
public void setLocale(Locale locale)
{
context.setLocale(locale);
}
#Override
public void setPropertyResolved(boolean resolved)
{
context.setPropertyResolved(resolved);
}
#Override
public FunctionMapper getFunctionMapper()
{
return context.getFunctionMapper();
}
#Override
public VariableMapper getVariableMapper()
{
return context.getVariableMapper();
}
}
private static class InterceptingResolver extends ELResolver
{
private final ELResolver delegate;
private ValueReference valueReference;
public InterceptingResolver(ELResolver delegate)
{
this.delegate = delegate;
}
public ValueReference getValueReference()
{
return valueReference;
}
// Capture the base and property rather than write the value
#Override
public void setValue(ELContext context, Object base, Object property, Object value)
{
if(base != null && property != null)
{
context.setPropertyResolved(true);
valueReference = new ValueReference(base, property.toString());
}
}
// The rest of the methods simply delegate to the existing context
#Override
public Object getValue(ELContext context, Object base, Object property)
{
return delegate.getValue(context, base, property);
}
#Override
public Class<?> getType(ELContext context, Object base, Object property)
{
return delegate.getType(context, base, property);
}
#Override
public boolean isReadOnly(ELContext context, Object base, Object property)
{
return delegate.isReadOnly(context, base, property);
}
#Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base)
{
return delegate.getFeatureDescriptors(context, base);
}
#Override
public Class<?> getCommonPropertyType(ELContext context, Object base)
{
return delegate.getCommonPropertyType(context, base);
}
}
}
Have a look at Omnifaces ExpressionInspector. Seems in JSF 2.x its not implemented and always returns null.
https://showcase.omnifaces.org/el/ExpressionInspector
Related
My search view is working properly but I am trying to do a search such that all the "visible" search letters should be highlighted. I used the filter interface in my adapter for filtering data.
here is my adapter Class
public class myAdapter extends RecyclerView.Adapter<myAdapter.viewHolder> implements Filterable {
private List<Model> model;
// for search filtering
private ArrayList<Model> modelFull;
Context context;
public myAdapter(ArrayList<Model> model, Context context) {
this.model = model;
modelFull =new ArrayList<>(model);
this.context = context;
}
#NonNull
#Override
public viewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.template, parent, false);
return new viewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull viewHolder holder, int position) {
Model forPosition = model.get(position);
holder.image.setImageResource(forPosition.getImage());
holder.intro.setText(forPosition.getIntro());
}
#Override
public int getItemCount() {
return model.size();
}
public class viewHolder extends RecyclerView.ViewHolder {
TextView intro;
ImageView image;
public viewHolder(#NonNull View itemView) {
super(itemView);
intro= itemView.findViewById(R.id.introTxt);
image = itemView.findViewById(R.id.image);
}
}
#Override
public Filter getFilter() {
return generalFilter;
}
private Filter generalFilter =new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Model> filteredModel =new ArrayList<>();
if(constraint ==null || constraint.length()==0) {
filteredModel.addAll(modelFull);
}
else {
String searchQuery= constraint.toString().toLowerCase().trim();
for(blogBigModel item : modelFull){
if(item.getBlogIntro().toLowerCase().contains(searchQuery)){
filteredModel.add(item);
}
}
}
FilterResults results =new FilterResults();
results.values = filteredModel;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
model.clear();
model.addAll((List)results.values);
notifyDataSetChanged();
}
};
}
that's my class / Fragment where i used the above adapter
[what should i add to get the desired highlighted query when i search in the search bar like Whatsapp][1]
[1]: https://i.stack.imgur.com/Fdu2r.jpg
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.ic_home_search:enter code here
SearchView searchView = (SearchView) item.getActionView();
searchView.setQueryHint("Search....");
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setBackground(getResources().getDrawable(R.drawable.searchview_bg));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
}
return true;
});
I want to filter Listview by Searchview
I use the following Adapter for the filter and it works if I haven't made any new additions to the adapter
When I add a new item to Listview, the search stops completely until I restart the program after adding, modifying or deleting it
full code
adapter class
Do you want to achieve the result like following GIF?
If you want to add the item to the listview, based on your adapter, you should item in the adapter like following code.
public class TableItemAdapter : BaseAdapter<TableItem>, IFilterable
{
public List<TableItem> _originalData;
public List<TableItem> _items;
private readonly Activity _context;
public TableItemAdapter(Activity activity, IEnumerable<TableItem> tableitems)
{
_items = tableitems.ToList();
_context = activity;
Filter = new TableItemFilter(this);
}
//Add data to the `_items`, listview will be updated, if add data in the activity,
//there are two different lists, so listview will not update.
public void AddData(TableItem tableItem)
{
_items.Add(tableItem);
NotifyDataSetChanged();
}
public override TableItem this[int position]
{
get { return _items[position]; }
}
public Filter Filter { get; private set; }
public override int Count
{
get { return _items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = _items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = convertView ?? _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
//view = _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
return view;
}
public override void NotifyDataSetChanged()
{
// this.NotifyDataSetChanged();
base.NotifyDataSetChanged();
}
}
public class TableItemFilter :Filter
{
private readonly TableItemAdapter _adapter;
public TableItemFilter(TableItemAdapter adapter)
{
_adapter = adapter;
}
protected override FilterResults PerformFiltering(ICharSequence constraint)
{
var returnObj = new FilterResults();
var results = new List<TableItem>();
if (_adapter._originalData == null)
_adapter._originalData = _adapter._items;
if (constraint == null) return returnObj;
if (_adapter._originalData != null && _adapter._originalData.Any())
{
results.AddRange(
_adapter._originalData.Where(
item => item.SubHeading.ToLower().Contains(constraint.ToString()) | item.Heading.ToLower().Contains(constraint.ToString())));
}
returnObj.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray());
returnObj.Count = results.Count;
constraint.Dispose();
return returnObj;
}
protected override void PublishResults(ICharSequence constraint, FilterResults results)
{
using (var values = results.Values)
_adapter._items = values.ToArray<Java.Lang.Object>().Select(r => r.ToNetObject<TableItem>()).ToList();
_adapter.NotifyDataSetChanged();
// Don't do this and see GREF counts rising
constraint.Dispose();
results.Dispose();
}
}
public class JavaHolder : Java.Lang.Object
{
public readonly object Instance;
public JavaHolder(object instance)
{
Instance = instance;
}
}
public static class ObjectExtensions
{
public static TObject ToNetObject<TObject>(this Java.Lang.Object value)
{
if (value == null)
return default(TObject);
if (!(value is JavaHolder))
throw new InvalidOperationException("Unable to convert to .NET object. Only Java.Lang.Object created with .ToJavaObject() can be converted.");
TObject returnVal;
try { returnVal = (TObject)((JavaHolder)value).Instance; }
finally { value.Dispose(); }
return returnVal;
}
public static Java.Lang.Object ToJavaObject<TObject>(this TObject value)
{
if (Equals(value, default(TObject)) && !typeof(TObject).IsValueType)
return null;
var holder = new JavaHolder(value);
return holder;
}
}
}
Then in the activity, you add the data by adapter.
private void Button1_Click(object sender, System.EventArgs e)
{
tableItemAdapter.AddData(new TableItem() { Heading = "test1222", SubHeading = "sub Test" });
}
Here is my demo, you can download it.
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/XAListViewSearchDemo.zip
I'm trying to understand Jersey 2 development and context-dependency injection.
I don't understand how to inject into a resource an object that needs initialization parameters in the constructor.
For example: I'd like to #Inject slf4j Logger, built using LoggerFactory.
My resource class is:
#Path("/myresource")
public class MyResource {
#Inject
private Logger log;
#GET
#Produces(MediaType.APPLICATION_JSON)
public Answer status() {
log.info("STATUS");
return new Answer(200, "Server up and running # "+ ZonedDateTime.now());
}
}
My Resource config is:
public class MyAppextends ResourceConfig {
public MyApp() {
register(new MyBinder());
packages(true, "my.packages");
}
}
public class MyBinder extends AbstractBinder {
#Override
protected void configure() {
bindFactory(MyLoggerFactory.class).to(org.slf4j.Logger.class);
}
}
Finally, the Factory is:
public class MyLoggerFactory implements Factory<Logger> {
#Override
public Logger provide() {
return LoggerFactory.getLogger(TYPE_FOR_LOGGING.class);
}
#Override
public void dispose(Logger logger) {
}
}
How can I specify TYPE_FOR_LOGGING as argument, in order to Inject the correctly initialized Logger in every resource I want?
Thanks
What you are looking for is called the InstantiationService. You can inject it into Factories to find out who is calling the factory inside of the provide method.
Below find a code sample from the hk2 tests that illustrate the use of the InstantiationService.
#Singleton
public class CorrelationFactory implements Factory<PerLookupServiceWithName> {
private final static PerLookupServiceWithName NULL_SERVICE = new PerLookupServiceWithName() {
#Override
public String getName() {
return null;
}
};
#Inject
private InstantiationService instantiationService;
/* (non-Javadoc)
* #see org.glassfish.hk2.api.Factory#provide()
*/
#Override #PerLookup
public PerLookupServiceWithName provide() {
InstantiationData data = instantiationService.getInstantiationData();
if (data == null) {
return NULL_SERVICE;
}
Injectee parent = data.getParentInjectee();
if (parent == null) {
return NULL_SERVICE;
}
Class<?> parentClass = parent.getInjecteeClass();
if (parentClass == null) {
return NULL_SERVICE;
}
Correlator correlator = parentClass.getAnnotation(Correlator.class);
if (correlator == null) {
return NULL_SERVICE;
}
final String fName = correlator.value();
return new PerLookupServiceWithName() {
#Override
public String getName() {
return fName;
}
};
}
/* (non-Javadoc)
* #see org.glassfish.hk2.api.Factory#dispose(java.lang.Object)
*/
#Override
public void dispose(PerLookupServiceWithName instance) {
// DO nothing
}
}
i'm using spring-boot-starter-data-elasticsearch (1.4.0.M3).
I'm unable to get the version (_version in elasticsearch query result) of a document using the annoation "version".
Any idea why the annotation isn't working ?
f.e.:
#GwtCompatible
#Document(indexName = "myIndexName")
public class Catalog implements Serializable {
private List<GroupProduct> groups;
#Id
private String uuid;
#Version
private Long version;
#Field(type = FieldType.Nested)
private List<Product> products;
private String label;
#NotEmpty
private String organizationUuid;
private List<String> organizationUnitUuids;
private Date updateDate;
private List<VAT> vats;
public Catalog() {
}
public List<GroupProduct> getGroups() {
return groups;
}
public List<Product> getProducts() {
return products;
}
public Date getUpdateDate() {
return updateDate;
}
public void setGroups(List<GroupProduct> groups) {
this.groups = groups;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public List<VAT> getVats() {
return vats;
}
public void setVats(List<VAT> vats) {
this.vats = vats;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getOrganizationUuid() {
return organizationUuid;
}
public void setOrganizationUuid(String organizationUuid) {
this.organizationUuid = organizationUuid;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public List<String> getOrganizationUnitUuids() {
return organizationUnitUuids;
}
public void setOrganizationUnitUuids(List<String> organizationUnitUuids) {
this.organizationUnitUuids = organizationUnitUuids;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
}
Spring Data Elasticsearch (as of version 2.0.2) seems to have only partial support for the #Version annotation. If you annotate a document with a version field, it will be used when indexing a document. It will tell Elasticsearch that the document being saved is that specified version. If the new version is less than or equal to the version of the current document, Elasticsearch will throw a VersionConflictEngineException.
Unfortunately, Spring does not appear to populate this version field when a document is retrieved. As far as I can tell, this makes the version annotation useless. Perhaps the project will add this support in the near future. In the meantime, I have found a workaround by extending the default ResultMapper that Spring uses:
public class ExtendedResultMapper extends DefaultResultMapper {
protected MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
public ExtendedResultMapper(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
super(mappingContext);
this.mappingContext = mappingContext;
}
#Override
public <T> T mapResult(GetResponse response, Class<T> clazz) {
T result = super.mapResult(response, clazz);
if (result != null) {
setPersistentEntityVersion(result, response.getVersion(), clazz);
}
return result;
}
#Override
public <T> LinkedList<T> mapResults(MultiGetResponse responses, Class<T> clazz) {
LinkedList<T> results = super.mapResults(responses, clazz);
if (results != null) {
for (int i = 0; i < results.size(); i++) {
setPersistentEntityVersion(results.get(i), responses.getResponses()[i].getResponse().getVersion(), clazz);
}
}
return results;
}
private <T> void setPersistentEntityVersion(T result, Long version, Class<T> clazz) {
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
PersistentProperty<ElasticsearchPersistentProperty> versionProperty = mappingContext.getPersistentEntity(clazz).getVersionProperty();
if (versionProperty != null && versionProperty.getType().isAssignableFrom(Long.class)) {
Method setter = versionProperty.getSetter();
if (setter != null) {
try {
setter.invoke(result, version);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
}
}
You can tell Spring to use this version instead of the default mapper as follows:
#Autowired
private Client client;
#Bean
public ElasticsearchTemplate elasticsearchTemplate() {
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
ExtendedResultMapper mapper = new ExtendedResultMapper(converter.getMappingContext());
return new ElasticsearchTemplate(client, converter, mapper);
}
Note that the version is only populated for Get or Multi-Get requests. Search results do not include version information.
You could also use this same approach to extract other information from the GetResponse objects.
Using this code, if you get a document and then try to save it back, it will fail unless you increment the version.
Could anyone explain me one thing? Is it possible to use Vaadin TreeTable with LazyQueryContainer? I've alredy tried but it doesn't work. Actually, there is no any lazy loading. The method loadItems of org.vaadin.addons.lazyquerycontainer.Query is called until all data are loaded. For instanse, if batch size for the container = 100 and I have 500 rows then this method will be called 5 times. Here is my code:
public class LazyHierarchicalQueryContainer extends LazyQueryContainer implements Container.Hierarchical {
private String parentProperty = "parent";
public LazyHierarchicalQueryContainer(QueryFactory queryFactory, Object idPropertyId, int batchSize,
boolean compositeItems) {
super(queryFactory, idPropertyId, batchSize, compositeItems);
}
public LazyHierarchicalQueryContainer(QueryDefinition queryDefinition, QueryFactory queryFactory) {
super(queryDefinition, queryFactory);
}
public LazyHierarchicalQueryContainer(QueryView queryView) {
super(queryView);
}
public String getParentProperty() {
return parentProperty;
}
public void setParentProperty(String parentProperty) {
this.parentProperty = parentProperty;
}
#Override
public Collection<?> getChildren(Object itemId) {
return Collections.emptyList();
}
#Override
public Object getParent(Object itemId) {
return null;
}
#Override
public Collection<?> rootItemIds() {
ArrayList arrayList = new ArrayList();
for (Object workItem : getItemIds()) {
if (isRoot(workItem)) {
arrayList.add(workItem);
}
}
return arrayList;
}
#Override
public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
if (getItem(newParentId) != null) {
getItem(itemId).getItemProperty(getParentProperty()).setValue(newParentId);
} else {
getItem(itemId).getItemProperty(getParentProperty()).setValue(null);
}
return true;
}
#Override
public boolean areChildrenAllowed(Object itemId) {
return true;
}
#Override
public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
return false;
}
#Override
public boolean isRoot(Object itemId) {
return getItem(itemId).getItemProperty(parentProperty).getValue() == null;
}
#Override
public boolean hasChildren(Object itemId) {
return false;
}
}
Thanks in advance.
It seems your implementation of rootItemIds() loads all items to filter out the root items. This may cause the whole container to be read in the first go.