I have a problem with the Wicket 8 ModalWindow return value, I refer to Modal window, and it works fine.
I added a PageableListView to the instance (see Pageables Example) and it works fine.
In order to use DATABASE data, I use IModel to perform data query. I don’t set the query conditions on the home page, and they all work normally.
However, when I pass the value back to PageableListView through the modal window, a NullPointerException will appear in the modal window.
Thanks in advance.
Here is my code
ListModalTab.java
public class ListModalTab extends BasePage {
private static final long serialVersionUID = 1L;
#SpringBean
private TabHService oTabHService_;
private PageableListView cTabHListView_;
public ListModalTab() {
final Form cForm = new Form("form");
final Label result;
cForm.add(result = new Label("result", new PropertyModel<>(this, "result")));
result.setOutputMarkupId(true);
final ModalWindow modal1;
cForm.add(modal1 = new ModalWindow("modal1"));
modal1.setCookieName("modal-1");
modal1.setPageCreator(() -> new QueryModalTab(ListModalTab.this.getPageReference(), modal1));
modal1.setWindowClosedCallback(target -> target.add(cForm));
modal1.setOutputMarkupId(true);
modal1.setCloseButtonCallback(target -> {
setResult("Modal window 1 - close button");
return true;
});
cForm.add(new AjaxLink<Void>("showModal1") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
modal1.show(target);
}
});
final WebMarkupContainer cContainer = new WebMarkupContainer("container");
cContainer.setOutputMarkupId(true);
cForm.add(cContainer);
/*
* Data query using IModel
*/
TabH oConstraintEntity = new TabH();
IModel mTabHListViewModel = new Model() {
public java.io.Serializable getObject() {
return (Serializable) oTabHService_.queryByTabH(oConstraintEntity);
}
};
/*
* Use string array data
*/
//final String[] names = { "Doe, John", "Presley, Elvis", "Presly, Priscilla",
// "Hasselhoff, David", "Moore, Demi", };
/*
* PageableListView is working properly if used with string array
*/
// PageableListView<String> listview = new PageableListView<String>("rows", Arrays.asList(names), 1) {
// #Override
// protected void populateItem(ListItem<String> item) {
// item.add(new Label("tabId", item.getModelObject()));
// }
// };
/*
* If the PageableListView is passed in using an IModel Object, the modal window will have a NullPointerException.
*/
PageableListView<TabH> listview = new PageableListView<TabH>("rows", mTabHListViewModel, 1) {
#Override
protected void populateItem(ListItem<TabH> item) {
final TabH oTabH = (TabH) item.getModelObject();
item.add(new Label("tabId", oTabH.getTabId()));
}
};
cContainer.add(listview);
cContainer.add(new AjaxPagingNavigator("navigator", listview));
this.add(cForm);
}
/**
* #return the result
*/
public String getResult() {
return result;
}
/**
* #param result
* the result to set
*/
public void setResult(String result) {
this.result = result;
}
private String result;}
QueryModalTab.java
public class QueryModalTab extends WebPage {
private static final long serialVersionUID = 1L;
private TabH tabH = new TabH();
public QueryModalTab(final PageReference modalWindowPage, final ModalWindow window) {
CompoundPropertyModel mTabH = new CompoundPropertyModel(tabH);
Form cForm = new Form("form", mTabH);
TextField cTabId = new TextField("tabId");
cForm.add(cTabId);
TextField cTabName = new TextField("tabName");
cForm.add(cTabName);
cForm.add(new AjaxLink<Void>("closeOK") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
if (modalWindowPage != null)
((ListModalTab) modalWindowPage.getPage()).setResult("Modal window 1 - close link OK");
window.close(target);
}
});
/*
* NullPointerException appears in ((ListModalTab) modalWindowPage.getPage())
*/
AjaxSubmitLink cConfirm = new AjaxSubmitLink("confirm") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
super.onSubmit(target);
if (modalWindowPage != null)
((ListModalTab) modalWindowPage.getPage()).setResult(tabH.getTabId());
ModalWindow.closeCurrent(target);
}
};
cForm.add(cConfirm);
cForm.add(new AjaxLink<Void>("closeCancel") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
if (modalWindowPage != null)
((ListModalTab) modalWindowPage.getPage()).setResult("Modal window 1 - close link Cancel");
window.close(target);
}
});
this.add(cForm);
}
}
NullPointerException
Root cause:
java.lang.NullPointerException
at com.web.webpage.systempage.tab.QueryModalTab$2.onSubmit(QueryModalTab.java:52)
at org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink$1.onSubmit(AjaxSubmitLink.java:111)
at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior$AjaxFormSubmitter.onSubmit(AjaxFormSubmitBehavior.java:223)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1251)
at org.apache.wicket.markup.html.form.Form.process(Form.java:946)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:770)
at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:176)
at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:151)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:598)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.internalInvoke(ListenerRequestHandler.java:306)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invoke(ListenerRequestHandler.java:280)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invokeListener(ListenerRequestHandler.java:222)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.respond(ListenerRequestHandler.java:208)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:912)
at org.apache.wicket.request.RequestHandlerExecutor.execute(RequestHandlerExecutor.java:65)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:283)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:253)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:221)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:262)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:204)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:286)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Related
im newbie here... I have a problem in getting the item count on my recyclerview? I've try this code but it's not working.
int count = 0;
if (recyclerViewInstance.getAdapter() != null) {
count = recyclerViewInstance.getAdapter().getItemCount();
}
also this one but it's not working too..
int count = 0;
if (mAdapter != null) {
count = mAdapter.getItemCount();
}
this is my code:
mainActivity:
private List<NavDrawerFleetGetterSetter> navList= new ArrayList<>();
private RecyclerView recyclerView;
private NavDrawerFleetAdapter mAdapter;
Button add;
TextView successCount;
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nav_drawer_fleet);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
add = findViewById(R.id.fab);
successCount=findViewById(R.id.count);
recyclerView =findViewById(R.id.nav_sent);
mAdapter = new NavDrawerFleetAdapter(navList);
RecyclerView.LayoutManager mLayoutManager = new
LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(mAdapter);
if (recyclerView.getAdapter() != null) {
successCount.getText(recyclerViewInstance.getAdapter().getItemCount());
}
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavDrawerFleetGetterSetter navD= new
NavDrawerFleetGetterSetter(lati,longi,dateTime);
navList.add(navD);
mAdapter.notifyDataSetChanged();
}
myGetterSetter:
public class NotSentModuleGetterSetter {
String lat,lon,dateTime;
public NotSentModuleGetterSetter(String lat, String lon, String dateTime) {
this.lat = lat;
this.lon = lon;
this.dateTime = dateTime;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getDateTime() {
return dateTime;
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
}
myOutput:
as you see, the success count was turned into zero.
btw, my data was getting on my database and i was pickup the code need since i have a bunch of codes as for now for my project.
an also, using debug, the data of my mAdapter=null.
In this case, i was getting the count data on my adapter but it should be get the "Size" of adapter than getting the "count". It is now working on me. :)
I have a view where I have two tree viewers. In the createPartControl() how I can set the selectionProviders for both the views. It takes either one of them.
Here is my snippet.
The View code:
IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPartSite activePartSite = workbenchWindow.getActivePage().getActivePart().getSite();
activePartSite.setSelectionProvider(inputTreeViewer);
activePartSite.setSelectionProvider(compositeTreeViewer);
// Here the last line the selection provider code for the top one.
// Hence I only get selections from the second tree.
How can we solve the problem? I tried with inheriting the view class from ISelectionProvider and overriding getSelection() method. But that was not of any help.
Can someone suggest something?
I suggest to add a focus listener to each of the trees and call partSite.setSelectionProvider() with the currently focused tree viewer. For example:
treeViewer1.getTree().addListener( SWT.FocusIn, event -> site.setSelectionProvider( treeViewer1 ) );
treeViewer2.getTree().addListener( SWT.FocusIn, event -> site.setSelectionProvider( treeViewer2 ) );
I'll leave it as an exercise to the reader to remove the listener-duplication.
Alternatively, you can create a proxy selection provider that listens for selection changes in both tree viewers and propagates the most recent selection. Something along these lines:
public class ProxySelectionProvider implements ISelectionProvider {
private ISelection selection;
private final Collection<ISelectionChangedListener> listeners;
public ProxySelectionProvider( StructuredViewer... viewers ) {
listeners = new ArrayList<>();
selection = StructuredSelection.EMPTY;
for( StructuredViewer viewer : viewers ) {
ISelectionChangedListener selectionListener = this::selectionChanged;
viewer.addSelectionChangedListener( selectionListener );
viewer.getControl().addDisposeListener( event -> viewer.removeSelectionChangedListener( selectionListener ) );
}
}
#Override
public void addSelectionChangedListener( ISelectionChangedListener listener ) {
listeners.add( listener );
}
#Override
public void removeSelectionChangedListener( ISelectionChangedListener listener ) {
listeners.remove( listener );
}
#Override
public ISelection getSelection() {
return selection;
}
#Override
public void setSelection( ISelection selection ) {
this.selection = selection;
}
private void selectionChanged( SelectionChangedEvent event ) {
selection = event.getSelection();
notifyListeners();
}
private void notifyListeners() {
SelectionChangedEvent event = new SelectionChangedEvent( this, selection );
new ArrayList<>( listeners ).forEach( listener -> listener.selectionChanged( event ) );
}
}
Use the selection provider like this:
ISelectionProvider selectionProvider = new ProxySelectionProvider( treeViewer1, treeViewer2 );
IWorkbenchPartSite partSite = workbenchWindow.getActivePage().getActivePart().getSite();
partSite.setSelectionProvider( selectionProvider );
I solved this problem using this approach.
public class SelectionProviderAdapater implements IPostSelectionProvider {
public class InternalListener implements ISelectionChangedListener, FocusListener {
#Override
public void focusGained(FocusEvent e) {
doFocusChanged(e.widget);
}
#Override
public void focusLost(FocusEvent e) {
}
#Override
public void selectionChanged(SelectionChangedEvent event) {
doSelectionChanged(event);
}
}
/**
* The array of viewers.
*/
private StructuredViewer[] viewers;
/**
* The current viewer in focus.
*/
private StructuredViewer viewerInFocus;
/**
* The list of selection changed listeners.
*/
private final ListenerList selectionChangedListeners = new ListenerList();
/**
* The list of post selection changed listeners.
*/
private final ListenerList postSelectionChangedListeners = new ListenerList();
/**
* The internal listener instance.
*/
private final InternalListener internalListener = new InternalListener();
/**
* The internal post selection listener instance.
*/
private final ISelectionChangedListener internalPostSelectionListener = new ISelectionChangedListener() {
#Override
public void selectionChanged(SelectionChangedEvent event) {
doPostSelectionChanged(event);
}
};
#Override
public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
postSelectionChangedListeners.add(listener);
}
#Override
public void addSelectionChangedListener(ISelectionChangedListener listener) {
selectionChangedListeners.add(listener);
}
/**
* Sets the viewer in focus and fires selection change events.
*
* #param control
* The {#link Widget} that has gained focus.
*/
private void doFocusChanged(Widget control) {
for (StructuredViewer viewer : viewers) {
if (viewer.getControl() == control) {
propagateFocusChanged(viewer);
return;
}
}
}
/**
* Fires post selection changed events if the {#link SelectionChangedEvent}
* 's selection provider is the current viewer in focus.
*
* #param event
* The selection changed event.
*/
private void doPostSelectionChanged(SelectionChangedEvent event) {
ISelectionProvider provider = event.getSelectionProvider();
if (provider == viewerInFocus) {
firePostSelectionChanged();
}
}
/**
* Fires selection changed events if the {#link SelectionChangedEvent}'s
* selection provider is the current viewer in focus.
*
* #param event
* The selection changed event.
*/
private void doSelectionChanged(SelectionChangedEvent event) {
ISelectionProvider provider = event.getSelectionProvider();
if (provider == viewerInFocus) {
fireSelectionChanged();
}
}
/**
* Notifies post selection changed listeners of a selection changed event.
*/
private void firePostSelectionChanged() {
if (postSelectionChangedListeners != null) {
SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
Object[] listeners = postSelectionChangedListeners.getListeners();
for (Object listener : listeners) {
ISelectionChangedListener selectionChangedListener = (ISelectionChangedListener) listener;
selectionChangedListener.selectionChanged(event);
}
}
}
/**
* Notifies selection changed listeners of a selection changed event.
*/
private void fireSelectionChanged() {
if (selectionChangedListeners != null) {
SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
Object[] listeners = selectionChangedListeners.getListeners();
for (Object listener : listeners) {
ISelectionChangedListener selectionChangedListener = (ISelectionChangedListener) listener;
selectionChangedListener.selectionChanged(event);
}
}
}
#Override
public ISelection getSelection() {
if (viewerInFocus != null) {
return viewerInFocus.getSelection();
}
return StructuredSelection.EMPTY;
}
public StructuredViewer getViewerInFocus() {
return viewerInFocus;
}
/**
* Sets the viewer as the viewer in focus and fires selection changed
* events.
*
* #param viewer
* The new viewer in focus.
*/
private void propagateFocusChanged(StructuredViewer viewer) {
if (viewer != viewerInFocus) {
viewerInFocus = viewer;
fireSelectionChanged();
firePostSelectionChanged();
}
}
#Override
public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
postSelectionChangedListeners.remove(listener);
}
#Override
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
selectionChangedListeners.remove(listener);
}
#Override
public void setSelection(ISelection selection) {
if (viewerInFocus != null) {
viewerInFocus.setSelection(selection);
}
}
/**
* Sets the selection on the current viewer in focus.
*
* #param selection
* The selection to set.
* #param reveal
* true if the selection is to be made visible, and false
* otherwise
*/
public void setSelection(ISelection selection, boolean reveal) {
if (viewerInFocus != null) {
viewerInFocus.setSelection(selection, reveal);
}
}
/**
* Sets the collection of viewers to be monitored by this mediator.
*
* #param newViewers
* The collection of viewers.
*/
public void setViewers(Collection<? extends StructuredViewer> newViewers) {
// Remove listeners from any previous viewers.
if (viewers != null) {
for (StructuredViewer viewer : viewers) {
viewer.removeSelectionChangedListener(internalListener);
viewer.removePostSelectionChangedListener(internalPostSelectionListener);
Control control = viewer.getControl();
if (!control.isDisposed()) {
control.removeFocusListener(internalListener);
}
}
}
viewers = null;
viewerInFocus = null;
if (newViewers != null) {
viewers = newViewers.toArray(new StructuredViewer[newViewers.size()]);
for (StructuredViewer viewer : viewers) {
viewer.addSelectionChangedListener(internalListener);
viewer.addPostSelectionChangedListener(internalPostSelectionListener);
Control control = viewer.getControl();
control.addFocusListener(internalListener);
if (control.isFocusControl()) {
propagateFocusChanged(viewer);
}
}
}
}
}
Create an instance of this class in your view.Set the viewers using setViewers() method which are needed to be listened for selection.Then set it as the selection provider.It should start working.
for my Wicket Wizard I want to display an information like: "Wizard step 1 of 4". I started by getting the number of steps and I already came across the first problem:
public WizardPanel(String id) {
super(id, false);
// false deactivates the default style.
setDefaultModel(new CompoundPropertyModel<WizardPanel>(this));
WizardModel model = new WizardModel();
model.add(new FirstStep());
model.add(new SecondStep());
model.add(new ThirdStep());
model.add(new ConfirmationStep());
Iterator<IWizardStep> iterator = model.stepIterator();
for(int i = 1; iterator.hasNext(); i ++){
System.out.println(String.valueOf(i));
}
init(model);
}
My Iterator creates an infinite loop. Shouldn't there only be four objects he can iterate through?
Or is there even a basic implementation for this kind of pagination I haven't found yet?
Because my next step would be to get the current index out of model.getActiveStep(); and find which number it is.
I thought I share my solution (as far as it now is)
public class OverviewComponent extends Panel{
private static final long serialVersionUID = 1L;
private List<WizardStep> steps;
private WizardModel model;
public OverviewComponent(String id, WizardModel model) {
super(id);
this.model = model;
steps = fillList();
this.add(new ListView<WizardStep>("steps", steps) {
private static final long serialVersionUID = 1L;
/**
* Wrap a markup container around the item append a css attribute to every item
*/
#Override
protected void populateItem(ListItem<WizardStep> item) {
WebMarkupContainer stepOverviewItem;
item.add(stepOverviewItem = new WebMarkupContainer("stepOverviewItem"));
stepOverviewItem.add(new Label("index", Model.of(item.getIndex()+1)));
stepOverviewItem.add(new AttributeModifier("class", getCSSProperty(item.getModelObject())));
stepOverviewItem.setOutputMarkupId(true);
stepOverviewItem.setOutputMarkupPlaceholderTag(true);
}
});
}
public String getCSSProperty(WizardStep step) {
if (step.equals(model.getActiveStep())) {
return "active";
} else if (!step.isComplete()) {
return "pending";
} else if (step.isComplete()) {
return "completed";
}
return "";
}
public List<WizardStep> fillList() {
List<WizardStep> iSteps = new ArrayList<WizardStep>();
Iterator<IWizardStep> iterator = model.stepIterator();
while (iterator.hasNext()) {
iSteps.add((WizardStep)iterator.next());
}
return iSteps;
}
}
I've added an index to a cache. The index uses a custom extractor that extends AbstractExtractor and overrides only the extract method to return a List of Strings. Then I have a ContainsFilter which uses the same custom extractor that looks for the occurence of a single String in the List of Strings. It does not look like my index is being used based on the time it takes to execute my test. What am I doing wrong? Also, is there some debugging I can switch on to see which indices are used?
public class DependencyIdExtractor extends AbstractExtractor {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public Object extract(Object oTarget) {
if (oTarget == null) {
return null;
}
if (oTarget instanceof CacheValue) {
CacheValue cacheValue = (CacheValue)oTarget;
// returns a List of String objects
return cacheValue.getDependencyIds();
}
throw new UnsupportedOperationException();
}
}
Adding the index:
mCache = CacheFactory.getCache(pCacheName);
mCache.addIndex(new DependencyIdExtractor(), false, null);
Performing the ContainsFilter query:
public void invalidateByDependencyId(String pDependencyId) {
ContainsFilter vContainsFilter = new ContainsFilter(new DependencyIdExtractor(), pDependencyId);
#SuppressWarnings("rawtypes")
Set setKeys = mCache.keySet(vContainsFilter);
mCache.keySet().removeAll(setKeys);
}
I solved this by adding a hashCode and equals method implementation to the DependencyIdExtractor class. It is important that you use exactly the same value extractor when adding an index and creating your filter.
public class DependencyIdExtractor extends AbstractExtractor {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public Object extract(Object oTarget) {
if (oTarget == null) {
return null;
}
if (oTarget instanceof CacheValue) {
CacheValue cacheValue = (CacheValue)oTarget;
return cacheValue.getDependencyIds();
}
throw new UnsupportedOperationException();
}
#Override
public int hashCode() {
return 1;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof DependencyIdExtractor) {
return true;
}
return false;
}
}
To debug Coherence indices/queries, you can generate an explain plan similar to database query explain plans.
http://www.oracle.com/technetwork/tutorials/tutorial-1841899.html
#SuppressWarnings("unchecked")
public void invalidateByDependencyId(String pDependencyId) {
ContainsFilter vContainsFilter = new ContainsFilter(new DependencyIdExtractor(), pDependencyId);
if (mLog.isTraceEnabled()) {
QueryRecorder agent = new QueryRecorder(RecordType.EXPLAIN);
Object resultsExplain = mCache.aggregate(vContainsFilter, agent);
mLog.trace("resultsExplain = \n" + resultsExplain + "\n");
}
#SuppressWarnings("rawtypes")
Set setKeys = mCache.keySet(vContainsFilter);
mCache.keySet().removeAll(setKeys);
}
I'm new to lucene so I don't know if it is possible, but I have an index and I would like to get the total amount of phrases in a subset of the index(the subset is defined by a filter).
I can use FilteredQuery with my Filter and a PhraseQuery to search for the phrase and thus I can count the documents in which this phrase occurs, but I can't seem to find a way to count the number of matches per document as well.
You can do this, see LUCENE-2590 for details.
For example code you can look at the unit tests for this feature.
I've copied the relevant code for phrase searchers below,
This is the collector,
private static class CountingCollector extends Collector {
private final Collector other;
private int docBase;
public final Map<Integer, Map<Query, Float>> docCounts = new HashMap<Integer, Map<Query, Float>>();
private final Map<Query, Scorer> subScorers = new HashMap<Query, Scorer>();
private final ScorerVisitor<Query, Query, Scorer> visitor = new MockScorerVisitor();
private final EnumSet<Occur> collect;
private class MockScorerVisitor extends ScorerVisitor<Query, Query, Scorer> {
#Override
public void visitOptional(Query parent, Query child, Scorer scorer) {
if (collect.contains(Occur.SHOULD))
subScorers.put(child, scorer);
}
#Override
public void visitProhibited(Query parent, Query child, Scorer scorer) {
if (collect.contains(Occur.MUST_NOT))
subScorers.put(child, scorer);
}
#Override
public void visitRequired(Query parent, Query child, Scorer scorer) {
if (collect.contains(Occur.MUST))
subScorers.put(child, scorer);
}
}
public CountingCollector(Collector other) {
this(other, EnumSet.allOf(Occur.class));
}
public CountingCollector(Collector other, EnumSet<Occur> collect) {
this.other = other;
this.collect = collect;
}
#Override
public void setScorer(Scorer scorer) throws IOException {
other.setScorer(scorer);
scorer.visitScorers(visitor);
}
#Override
public void collect(int doc) throws IOException {
final Map<Query, Float> freqs = new HashMap<Query, Float>();
for (Map.Entry<Query, Scorer> ent : subScorers.entrySet()) {
Scorer value = ent.getValue();
int matchId = value.docID();
freqs.put(ent.getKey(), matchId == doc ? value.freq() : 0.0f);
}
docCounts.put(doc + docBase, freqs);
other.collect(doc);
}
#Override
public void setNextReader(IndexReader reader, int docBase)
throws IOException {
this.docBase = docBase;
other.setNextReader(reader, docBase);
}
#Override
public boolean acceptsDocsOutOfOrder() {
return other.acceptsDocsOutOfOrder();
}
}
The unit test is,
#Test
public void testPhraseQuery() throws Exception {
PhraseQuery q = new PhraseQuery();
q.add(new Term("f", "b"));
q.add(new Term("f", "c"));
CountingCollector c = new CountingCollector(TopScoreDocCollector.create(10,
true));
s.search(q, null, c);
final int maxDocs = s.maxDoc();
assertEquals(maxDocs, c.docCounts.size());
for (int i = 0; i < maxDocs; i++) {
Map<Query, Float> doc0 = c.docCounts.get(i);
assertEquals(1, doc0.size());
assertEquals(2.0F, doc0.get(q), FLOAT_TOLERANCE);
Map<Query, Float> doc1 = c.docCounts.get(++i);
assertEquals(1, doc1.size());
assertEquals(1.0F, doc1.get(q), FLOAT_TOLERANCE);
}
}