blob: 8a741bc9790cd77b84ee0550bc6944cc159db306 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2017 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*/
package org.eclipse.osbp.xtext.datamart.common;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent;
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherDataTag;
import org.eclipse.osbp.runtime.common.event.IDualData;
import org.eclipse.osbp.ui.api.datamart.DatamartFilter;
import org.eclipse.osbp.ui.api.datamart.DatamartFilter.FilterType;
import org.eclipse.osbp.ui.api.datamart.IDataMart;
import org.eclipse.osbp.ui.api.datamart.IDatamartBetweenInput;
import org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator;
import org.eclipse.osbp.ui.api.datamart.IDatamartSelectable;
import org.eclipse.osbp.ui.api.layout.IViewLayoutManager;
import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService;
import org.eclipse.osbp.ui.api.user.IUser;
import org.eclipse.osbp.xtext.i18n.I18NKeyGenerator;
import org.slf4j.Logger;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.UI;
// creates a filtermap from selected and multiselected components.
/**
* The Class DatamartFilterGenerator.
*/
// For cubes the class creates permutated slices over all filter aspects
@SuppressWarnings("serial")
public class DatamartFilterGenerator implements IDatamartFilterGenerator, ValueChangeListener, IUser.UserLocaleListener {
private static Logger logger = org.slf4j.LoggerFactory.getLogger(DatamartFilterGenerator.class);
/** The dsl metadata service. */
private transient IDSLMetadataService dslMetadataService;
/** The datamart. */
private transient IDataMart datamart;
/** The listeners. */
private transient List<FilterChangeListener> listeners = new CopyOnWriteArrayList<>();
/** avoid concurrent modification of vaadin **/
private LinkedBlockingQueue<ValueChangeEvent> queue = new LinkedBlockingQueue<>();
private AtomicBoolean active = new AtomicBoolean(false);
private transient Thread thread;
private boolean showCaption;
private int numMultiRows;
/**
* Instantiates a new datamart filter generator.
*
* @param datamart the datamart
* @param dslMetadataService the dsl metadata service
*/
public DatamartFilterGenerator(IDataMart datamart, IEclipseContext eclipseContext, boolean showCaption, int numMultiRows) {
this.datamart = datamart;
this.dslMetadataService = eclipseContext.get(IDSLMetadataService.class);
this.showCaption = showCaption;
this.numMultiRows = numMultiRows;
if(this.datamart != null && datamart.getUser() != null) {
this.datamart.getUser().addUserLocaleListener(this);
}
active.set(true);
final UI ui = eclipseContext.get(UI.class);
Runnable runnable = () -> {
while (active.get()) {
try {
ValueChangeEvent event;
try {
event = queue.take();
ui.access(() -> {
processValueChange(event);
});
} catch (InterruptedException e) {
}
} catch (Exception e) {
logger.error("{}", e);
}
}
};
thread = new Thread(runnable, "DatamartFilterGenerator eventProcessor " + getClass().getName());
thread.setDaemon(true);
thread.start();
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#addFilterChangeListener(org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator.FilterChangeListener)
*/
@Override
public void addFilterChangeListener(FilterChangeListener listener) {
if(!listeners.contains(listener)) {
listeners.add(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#removeChangeListener(org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator.FilterChangeListener)
*/
@Override
public void removeFilterChangeListener(FilterChangeListener listener) {
if(listeners.contains(listener)) {
listeners.remove(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#selectItem(java.lang.String, java.lang.String)
*/
@Override
public void selectItem(String filterID, String selection) {
if (selection != null && datamart != null) {
String sel = selection.replace("_", " ");
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
for (DatamartFilter filter : filters) {
if(filter.getType() != DatamartFilter.FilterType.BY_ID && filter.getName().equals(filterID)) {
for(IDualData item : filter.getData()) {
if(item.getSelectionValue().equals(sel)) {
filter.getSelector().select(item);
return;
}
}
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#selectItem(java.util.Map)
*/
@Override
public boolean selectItem(EventDispatcherEvent event, boolean byId) {
boolean mustRefresh = false;
for(DatamartFilter filter : datamart.getFilters()) {
switch (filter.getType()) {
case BY_ID:
if(byId && event.getData().containsKey(EventDispatcherDataTag.ID)) {
Object id = event.getData().get(EventDispatcherDataTag.ID);
if(event.getTopic().endsWith(filter.getShortName())) {
if(id instanceof Integer) {
filter.setSql(((Integer)id).toString());
} else if (id instanceof String) {
filter.setSql("'"+(String)id+"'");
} else {
filter.setSql("");
}
mustRefresh = true;
}
}
break;
case SINGLE:
if(filter.canSelectData(event.getData(), false, false)) {
filter.getSelector().select(filter.getSelectedData().get(0));
return false;
}
break;
case MULTIPLE:
if(filter.canSelectData(event.getData(), true, false)) {
filter.getSelector().select(filter.getSelectedData());
return false;
}
break;
case SINGLESLICER:
case SINGLEHIERARCHY:
case SINGLEHIERARCHYCHILDREN:
if(filter.canSelectData(event.getData(), false, true)) {
filter.getSelector().select(filter.getSelectedData().get(0));
return false;
}
break;
case EXCEPT:
case MULTIPLESLICER:
case MULTIPLEHIERARCHY:
case MULTIPLEHIERARCHYCHILDREN:
if(filter.canSelectData(event.getData(), true, true)) {
filter.getSelector().select(filter.getSelectedData());
return false;
}
break;
default:
break;
}
}
return mustRefresh;
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#resetItem(java.lang.String)
*/
@Override
public void resetItem(String filterID) {
if (datamart != null) {
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
for (DatamartFilter filter : filters) {
if(filter.getType() != DatamartFilter.FilterType.BY_ID) {
filter.getSelector().select(filter.getSelector().getFirstItem());
return;
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#createUIFilters(org.eclipse.osbp.ui.api.layout.IViewLayoutManager)
*/
@Override
public boolean createUIFilters(IViewLayoutManager layoutManager) {
DatamartUiFilterFactory filterFactory = new DatamartUiFilterFactory();
boolean hasFilters = false;
if(datamart != null) {
datamart.renderFilters();
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
hasFilters = true;
for (DatamartFilter filter : filters) {
switch (filter.getType()) {
case BY_ID:
break;
case SINGLE:
case SINGLESLICER:
case SINGLEHIERARCHY:
case SINGLEHIERARCHYCHILDREN:
filter.setSelector((IDatamartSelectable)filterFactory.getUiFilter(filter, numMultiRows));
layoutManager.getTopArea().addComponent((Component)filter.getSelector());
break;
case EXCEPT:
case MULTIPLE:
case MULTIPLESLICER:
case MULTIPLEHIERARCHY:
case MULTIPLEHIERARCHYCHILDREN:
filter.setSelector((IDatamartSelectable)filterFactory.getUiFilter(filter, numMultiRows));
layoutManager.getSideArea().addComponent((Component)filter.getSelector());
break;
case BETWEEN:
case BETWEEN_DATE:
filter.setBetweenInputComponent((IDatamartBetweenInput)filterFactory.getUiFilter(filter, numMultiRows));
layoutManager.getTopArea().addComponent((Component) filter.getBetweenInputComponent());
break;
}
if(filter.getType() != DatamartFilter.FilterType.BY_ID) {
if (DatamartFilter.FilterType.BETWEEN == filter.getType() || DatamartFilter.FilterType.BETWEEN_DATE == filter.getType()){
filter.getBetweenInputComponent().addValueChangeListener(this);
} else {
filter.getSelector().addValueChangeListener(this);
}
}
}
}
localeChanged(datamart.getUser().getLocale());
getSelections();
}
return hasFilters;
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator#updateFilter()
*/
@Override
public void updateFilter() {
if(datamart != null) {
datamart.renderFilters();
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
for (DatamartFilter filter : filters) {
if(filter.getType() != DatamartFilter.FilterType.BY_ID) {
filter.getSelector().update(filter.getData());
}
}
}
}
}
/**
* Gets the selections.
*
* @return the selections
*/
private boolean getSelections() {
boolean allFiltersSet = true;
if(datamart != null) {
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
for (DatamartFilter filter : filters) {
filter.clearSelectedData();
switch (filter.getType()) {
case BY_ID:
break;
case SINGLE:
case SINGLESLICER:
case SINGLEHIERARCHY:
case SINGLEHIERARCHYCHILDREN:
if(filter.getSelector().getValue() != null) {
filter.addSelectedItem((IDualData)filter.getSelector().getValue());
} else {
filter.clearSelectedData();
allFiltersSet = false;
}
break;
case EXCEPT:
filter.setSelectedData(filter.getSelector().getSelectedItems());
break;
case MULTIPLE:
case MULTIPLESLICER:
case MULTIPLEHIERARCHY:
case MULTIPLEHIERARCHYCHILDREN:
filter.setSelectedData(filter.getSelector().getSelectedItems());
if(filter.getSelector().getSelectedItems().isEmpty()) {
allFiltersSet = false;
}
break;
default:
break;
}
}
}
}
return allFiltersSet;
}
/**
* Strip MDX characters.
*
* @param filterName the filter name
* @return the string
*/
private String stripMDXCharacters(String filterName) {
return filterName.replace("[", "").replace("]", "");
}
/**
* Gets the translatable key.
*
* @param filterName the filter name
* @return the translatable key
*/
private String getTranslatableKey(String filterName) {
return I18NKeyGenerator.key(stripHierarchy(filterName));
}
/**
* Strip hierarchy.
*
* @param filterName the filter name
* @return the string
*/
private String stripHierarchy(String filterName) {
String result = filterName;
String[] parts = stripMDXCharacters(filterName).split("\\.");
int len = parts.length;
if (len > 0) {
result = parts[len - 1];
}
return result.replace(".", " ");
}
/* (non-Javadoc)
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(com.vaadin.data.Property.ValueChangeEvent)
*/
@Override
public void valueChange(ValueChangeEvent event) {
synchronized (queue) {
queue.offer(event);
}
}
protected void processValueChange(ValueChangeEvent event) {
// compute selections
if(getSelections()) {
// get the filter that changed
DatamartFilter changedFilter = null;
if(datamart != null) {
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
for (DatamartFilter filter : filters) {
if (filter.getType() == DatamartFilter.FilterType.BETWEEN || filter.getType() == DatamartFilter.FilterType.BETWEEN_DATE) {
if (!filter.getBetweenInputComponent().getFrom().isEmpty() && filter.getBetweenInputComponent().getUntilInput().equals(event.getProperty())){
changedFilter = filter;
break;
}
} else if (filter.getType() != DatamartFilter.FilterType.BY_ID && filter.getSelector().equals(event.getProperty())) {
changedFilter = filter;
break;
}
}
}
}
// notify the listeners of the changed filter
for(FilterChangeListener listener:listeners) {
if(changedFilter != null) {
listener.filterChanged(changedFilter);
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.osbp.ui.api.user.IUser.UserLocaleListener#localeChanged(java.util.Locale)
*/
@Override
public void localeChanged(final Locale locale) {
if(datamart != null) {
ArrayList<DatamartFilter> filters = datamart.getFilters();
if (filters != null) {
for (DatamartFilter filter : filters) {
if(filter.getSelector() != null || filter.getBetweenInputComponent() != null) {
StringBuilder text = new StringBuilder();
if(filter.getType()==FilterType.EXCEPT) {
text.append(dslMetadataService.translate(locale.toLanguageTag(), "exceptFor"));
text.append(" ");
}
text.append(dslMetadataService.translate(locale.toLanguageTag(), getTranslatableKey(filter.getName())));
if (showCaption) {
if (DatamartFilter.FilterType.BETWEEN == filter.getType() || DatamartFilter.FilterType.BETWEEN_DATE == filter.getType()) {
filter.getBetweenInputComponent().setCaption(text.toString());
} else {
filter.getSelector().setCaption(text.toString());
}
}
if (DatamartFilter.FilterType.BETWEEN == filter.getType() || DatamartFilter.FilterType.BETWEEN_DATE == filter.getType()) {
filter.getBetweenInputComponent().setDescription(text.toString());
} else {
filter.getSelector().setDescription(text.toString());
}
}
}
}
}
}
@Override
public boolean isPrimaryFilterId(EventDispatcherEvent event) {
return event.getTopic().endsWith(datamart.getPrimaryFilterId());
}
}