/*=============================================================================#
# Copyright (c) 2013-2016 Stephan Wahlbrink (WalWare.de) and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.rj.services.utils.dataaccess;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import de.walware.rj.data.RDataUtil;
import de.walware.rj.data.RLanguage;
import de.walware.rj.data.RObject;
import de.walware.rj.data.RVector;
import de.walware.rj.data.UnexpectedRDataException;
import de.walware.rj.data.defaultImpl.RObjectFactoryImpl;
import de.walware.rj.services.FunctionCall;
import de.walware.rj.services.IFQRObjectRef;
import de.walware.rj.services.RService;
/**
* Adapter interface to load R data in one- or two-dimensional fragments.
*
* @param <TRObject> type of R object
* @param <TFragmentObject> type of R object value fragments
* @since 2.0 (provisional)
*/
public abstract class AbstractRDataAdapter<TRObject extends RObject, TFragmentObject extends RObject> {
public static final int ROW_COUNT = 1 << 0;
public static final int STORE_TYPE = 1 << 2;
protected static void addXRef(final FunctionCall fcall, final IFQRObjectRef ref) {
fcall.add("x.env", ref.getEnv()); //$NON-NLS-1$
fcall.add("x.expr", RObjectFactoryImpl.INSTANCE.createExpression( //$NON-NLS-1$
"x.env$" + ((RLanguage) ref.getName()).getSource() )); //$NON-NLS-1$
}
public abstract TRObject validate(RObject rObject)
throws UnexpectedRDataException;
public abstract TRObject validate(RObject rObject, TRObject referenceObject, int flags)
throws UnexpectedRDataException;
public abstract long getRowCount(TRObject rObject);
public abstract long getColumnCount(TRObject rObject);
public void check(final IFQRObjectRef ref, final TRObject referenceObject,
final RService r, final IProgressMonitor monitor) throws CoreException,
UnexpectedRDataException {
final RObject result;
{ final FunctionCall fcall = r.createFunctionCall("rj:::.checkDataStruct"); //$NON-NLS-1$
addXRef(fcall, ref);
fcall.addChar("xClass1", referenceObject.getRClassName()); //$NON-NLS-1$
fcall.add("xDim", RObjectFactoryImpl.INSTANCE.createNumVector(new double[] { //$NON-NLS-1$
getRowCount(referenceObject),
getColumnCount(referenceObject),
}));
result = fcall.evalData(monitor);
}
if (RDataUtil.checkSingleLogiValue(result) == false) {
throw new UnexpectedRDataException("It seems something changed.");
}
}
public TFragmentObject loadData(final IFQRObjectRef ref, final TRObject referenceObject,
final LazyRStore.Fragment<TFragmentObject> fragment, final String rowMapping,
final RService r,
final IProgressMonitor monitor) throws CoreException, UnexpectedRDataException {
final RObject fragmentObject;
{ final FunctionCall fcall = r.createFunctionCall(getLoadDataFName());
addXRef(fcall, ref);
fcall.add("idxs", RObjectFactoryImpl.INSTANCE.createNumVector(new double[] { //$NON-NLS-1$
fragment.getRowBeginIdx() + 1,
fragment.getRowEndIdx(),
fragment.getColumnBeginIdx() + 1,
fragment.getColumnEndIdx(),
}));
if (rowMapping != null) {
fcall.addChar("rowMapping", rowMapping); //$NON-NLS-1$
}
fragmentObject = fcall.evalData(monitor);
}
return validateData(fragmentObject, referenceObject, fragment);
}
protected abstract String getLoadDataFName();
protected abstract TFragmentObject validateData(RObject rObject, TRObject referenceObject,
LazyRStore.Fragment<TFragmentObject> fragment)
throws UnexpectedRDataException;
public void setData(final IFQRObjectRef ref, final TRObject referenceObject,
final RDataAssignment assignment, final String rowMapping,
final RService r,
final IProgressMonitor monitor) throws CoreException, UnexpectedRDataException {
{ final FunctionCall fcall = r.createFunctionCall(getSetDataFName());
addXRef(fcall, ref);
fcall.add("idxs", RObjectFactoryImpl.INSTANCE.createNumVector(new double[] { //$NON-NLS-1$
assignment.getRowBeginIdx() + 1,
assignment.getRowEndIdx(),
assignment.getColumnBeginIdx() + 1,
assignment.getColumnEndIdx(),
}));
if (rowMapping != null) {
fcall.addChar("rowMapping", rowMapping); //$NON-NLS-1$
}
fcall.add("values", RObjectFactoryImpl.INSTANCE.createVector( //$NON-NLS-1$
assignment.getData() ));
fcall.evalVoid(monitor);
}
}
protected abstract String getSetDataFName();
public RVector<?> loadRowNames(final IFQRObjectRef ref, final TRObject referenceObject,
final LazyRStore.Fragment<RVector<?>> fragment, final String rowMapping,
final RService r, final IProgressMonitor monitor) throws CoreException,
UnexpectedRDataException {
final RObject fragmentObject;
{ final FunctionCall fcall = r.createFunctionCall(getLoadRowNamesFName());
addXRef(fcall, ref);
fcall.add("idxs", RObjectFactoryImpl.INSTANCE.createNumVector(new double[] { //$NON-NLS-1$
fragment.getRowBeginIdx() + 1,
fragment.getRowEndIdx(),
}));
if (rowMapping != null) {
fcall.addChar("rowMapping", rowMapping); //$NON-NLS-1$
}
fragmentObject = fcall.evalData(monitor);
}
return validateRowNames(fragmentObject, referenceObject, fragment);
}
protected abstract String getLoadRowNamesFName();
protected RVector<?> validateRowNames(final RObject rObject, final TRObject referenceObject,
final LazyRStore.Fragment<RVector<?>> fragment)
throws UnexpectedRDataException {
if (rObject.getRObjectType() == RObject.TYPE_NULL) {
return null;
}
final RVector<?> vector = RDataUtil.checkRVector(rObject);
RDataUtil.checkLengthEqual(vector.getData(), fragment.getRowCount());
return vector;
}
}