blob: d1af8d53da193eee352bef2089dd34852755eb55 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.ui.datafilter;
import java.util.Collection;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.r.core.RUtil;
import org.eclipse.statet.r.ui.dataeditor.RDataTableColumn;
import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RStore;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.services.FunctionCall;
import org.eclipse.statet.rj.ts.core.RToolService;
public class LevelVariableFilter extends VariableFilter {
private RStore availableValues;
private final IObservableSet<Object> selectedValues;
public LevelVariableFilter(final FilterSet set, final RDataTableColumn column) {
super(set, column);
this.availableValues= NO_VALUES;
this.selectedValues= new WritableSet<>(set.getRealm());
registerObservable(this.selectedValues);
}
@Override
public FilterType getType() {
return FilterType.LEVEL;
}
@Override
public void load(final VariableFilter filter) {
if (filter.getType() == FilterType.LEVEL) {
final LevelVariableFilter levelFilter= (LevelVariableFilter) filter;
runInRealm(new Runnable() {
@Override
public void run() {
LevelVariableFilter.this.selectedValues.addAll(levelFilter.getSelectedValues());
}
});
}
else if (filter.getType() == FilterType.TEXT) {
final TextVariableFilter textFilter= (TextVariableFilter)filter;
runInRealm(new Runnable() {
@Override
public void run() {
LevelVariableFilter.this.selectedValues.addAll(textFilter.getSelectedValues());
}
});
}
}
@Override
public void reset() {
runInRealm(new Runnable() {
@Override
public void run() {
LevelVariableFilter.this.selectedValues.clear();
}
});
}
@Override
protected void update(final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
final RDataTableColumn column= getColumn();
{ final FunctionCall fcall= r.createFunctionCall("rj:::.getDataLevelValues"); //$NON-NLS-1$
fcall.add(column.getRExpression());
fcall.addInt("max", 1000); //$NON-NLS-1$
final RObject data= fcall.evalData(m);
if (data.getRObjectType() == RObject.TYPE_NULL) {
setError(Messages.LevelFilter_TooMuch_message);
return;
}
RDataUtils.checkRVector(data);
if (column.getDataStore().getStoreType() == RStore.FACTOR) {
setValues(RDataUtils.checkData(data.getData(), RStore.CHARACTER));
}
else {
setValues(RDataUtils.checkData(data.getData(), column.getDataStore().getStoreType()));
}
return;
}
}
@Override
protected void setError(final String message) {
runInRealm(new Runnable() {
@Override
public void run() {
LevelVariableFilter.this.availableValues= NO_VALUES;
LevelVariableFilter.super.setError(message);
notifyListeners();
}
});
}
protected void setValues(final RStore values) {
runInRealm(new Runnable() {
@Override
public void run() {
if (!LevelVariableFilter.this.availableValues.equals(values) || getError() != null) {
LevelVariableFilter.this.availableValues= values;
LevelVariableFilter.super.setError(null);
notifyListeners();
}
}
});
}
@Override
protected String createFilter(final String varExpression) {
return createLevelFilter(this.availableValues, this.selectedValues, varExpression);
}
static String createLevelFilter(final RStore availableValues, final Collection<?> selectedValues,
final String varExpression) {
if (availableValues == null) {
return null;
}
final StringBuilder sb= new StringBuilder();
sb.append('(');
int num= 0;
int na= 0;
for (int i= 0; i < availableValues.getLength(); i++) {
final Object element= availableValues.get(i);
if (element == null) {
na= (selectedValues.contains(element)) ? 1 : -1;
continue;
}
if (selectedValues.contains(element)) {
if (num > 0) {
sb.append(" | "); //$NON-NLS-1$
}
sb.append(varExpression);
sb.append(" == "); //$NON-NLS-1$
if (element instanceof String) {
sb.append('"').append(RUtil.escapeCompletely((String) element)).append('"');
}
else {
sb.append(element);
}
num++;
}
}
if (num > 0 || na == 1) {
if (na >= 0) {
if (num > 0) {
sb.append(" | "); //$NON-NLS-1$
}
sb.append("is.na(").append(varExpression).append(')'); //$NON-NLS-1$
}
else {
if (num > 0) {
sb.insert(0, '(');
sb.append(')');
sb.append(" & "); //$NON-NLS-1$
}
sb.append("!is.na(").append(varExpression).append(')'); //$NON-NLS-1$
}
if (na == 1) {
num++;
}
}
sb.append(')');
return (sb.length() <= 2 || num == availableValues.getLength()) ? "" : sb.toString(); //$NON-NLS-1$
}
public RStore getAvailableValues() {
return this.availableValues;
}
public IObservableSet getSelectedValues() {
return this.selectedValues;
}
}