blob: 0c04b56ffa8a5189e8035e4107cc3b95f22d82b7 [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.core.pkgmanager;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.internal.r.core.RCorePlugin;
import org.eclipse.statet.rj.data.RCharacterStore;
import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.services.FunctionCall;
import org.eclipse.statet.rj.services.RService;
class RViewTasks {
private static class CRANViewHandler extends DefaultHandler {
private static final int S_VIEW= 1;
private static final int S_NAME= 2;
private static final int S_TOPIC= 3;
private static final int S_PKGLIST= 4;
private static final int S_PKGLIST_PKG= 5;
private final List<RView> viewList;
private RView view;
private final StringBuilder string= new StringBuilder();
private int state= -1;
private int depth;
private int skipDepth;
public CRANViewHandler(final List<RView> viewList) {
this.viewList= viewList;
}
@Override
public void startDocument() throws SAXException {
this.state= 0;
this.depth= 0;
this.skipDepth= Integer.MAX_VALUE;
}
@Override
public void endDocument() throws SAXException {
this.state= -1;
}
private void enter(final int newState) {
this.state= newState;
}
private void exit(final int newState) {
this.state= newState;
}
@Override
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes)
throws SAXException {
this.depth++;
if (this.depth < this.skipDepth) {
switch (this.state) {
case 0:
if (localName.equals("CRANTaskView")) { //$NON-NLS-1$
enter(S_VIEW);
this.view= null;
return;
}
break;
case S_VIEW:
if (localName.equals("name")) { //$NON-NLS-1$
if (this.view == null) {
enter(S_NAME);
this.string.setLength(0);
return;
}
}
else if (localName.equals("topic")) { //$NON-NLS-1$
if (this.view != null) {
enter(S_TOPIC);
this.string.setLength(0);
return;
}
}
else if (localName.equals("packagelist")) { //$NON-NLS-1$
if (this.view != null) {
enter(S_PKGLIST);
return;
}
}
break;
case S_PKGLIST:
if (localName.equals("pkg")) { //$NON-NLS-1$
enter(S_PKGLIST_PKG);
this.string.setLength(0);
return;
}
break;
}
this.skipDepth= this.depth;
}
}
@Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (this.depth < this.skipDepth) {
switch (this.state) {
case S_VIEW:
if (this.view != null && !this.view.getPkgList().isEmpty()) {
this.viewList.add(this.view);
this.view= null;
}
exit(0);
break;
case S_PKGLIST:
exit(S_VIEW);
break;
case S_NAME:
if (this.string.length() > 0) {
this.view= new RView(this.string.toString());
}
exit(S_VIEW);
break;
case S_TOPIC:
if (this.string.length() > 0) {
this.view.setTopic(this.string.toString());
}
exit(S_VIEW);
break;
case S_PKGLIST_PKG:
if (this.string.length() > 0) {
this.view.getPkgList().add(this.string.toString().intern());
}
exit(S_PKGLIST);
break;
}
}
else if (this.depth == this.skipDepth) {
this.skipDepth= Integer.MAX_VALUE;
}
this.depth--;
}
@Override
public void characters(final char[] ch, final int start, final int length) throws SAXException {
switch (this.state) {
case S_NAME:
case S_TOPIC:
case S_PKGLIST_PKG:
this.string.append(ch, start, length);
break;
}
}
}
static List<RView> loadRViews(final RService r, final ProgressMonitor m) {
final Exception error= null;
m.beginSubTask("Loading R task views...");
try {
final String dir;
{ final FunctionCall call= r.createFunctionCall("system.file"); //$NON-NLS-1$
call.addChar("ctv"); //$NON-NLS-1$
call.addChar("package", "ctv"); //$NON-NLS-1$ //$NON-NLS-2$
dir= RDataUtils.checkSingleChar(call.evalData(m));
}
if (dir == null || dir.equals("")) { //$NON-NLS-1$
return null;
}
final String[] files ;
{ final FunctionCall call= r.createFunctionCall("dir"); //$NON-NLS-1$
call.addChar("path", dir); //$NON-NLS-1$
final RCharacterStore data= RDataUtils.checkRCharVector(call.evalData(m)).getData();
files= data.toArray();
}
final List<RView> views= new ArrayList<>(files.length);
{ final String sep= r.getPlatform().getFileSep();
final CRANViewHandler handler= new CRANViewHandler(views);
final XMLReader reader= XMLReaderFactory.createXMLReader();
reader.setContentHandler(handler);
for (int i= 0; i < files.length; i++) {
if (files[i].endsWith(".ctv")) { //$NON-NLS-1$
final byte[] file= r.downloadFile(dir + sep + files[i], 0, m);
if (file.length > 0) {
reader.parse(new InputSource(new ByteArrayInputStream(file)));
}
}
}
}
return views;
}
catch (final StatusException | UnexpectedRDataException | IOException | SAXException e) {
RCorePlugin.logError("An error occurred when loading R task views.", error);
}
return null;
}
// private void loadBioCViews(final RService r, final ISelectedRepos repoSettings,
// final AvailableRPkgs pkgs, final Change event,
// final ProgressMonitor monitor) throws StatusException, UnexpectedRDataException, IOException {
// final IRPkgInfo pkg= getInstalled(pkgs, "biocViews"); //$NON-NLS-1$
// if (pkg == null || (pkg.getVersion().equals(this.biocViewsVersion)
// && Math.abs(event.stamp - biocViewsStamp) < MIRROR_CHECK ) ) {
// return;
// }
//
// Collection<RRepo> repos= repoSettings.getRepos();
// r.evalVoid("data(biocViewsVocab, package= 'biocViews', envir= rj::.rj.tmp)", monitor);
// for (RRepo repo : repos) {
// if (repo.getId().startsWith(RRepo.BIOC_ID_PREFIX)) {
// try {
// RObject data= r.evalData("biocViews:::getBiocViews('" + repo.getURL() + "', " +
// "rj::.rj.tmp$biocViewsVocab, 'NoViewProvided')", monitor );
// System.out.println(data);
// }
// catch (CoreException e) {
// e.printStackTrace();
// }
// }
// }
// final String dir;
// { final FunctionCall call= r.createFunctionCall("system.file"); //$NON-NLS-1$
// call.addChar("ctv"); //$NON-NLS-1$
// call.addChar("package", "ctv"); //$NON-NLS-1$
// dir= RDataUtils.checkSingleChar(call.evalData(monitor));
// }
// if (dir == null || dir.equals("")) { //$NON-NLS-1$
// return;
// }
//
// final String[] files ;
// { final FunctionCall call= r.createFunctionCall("dir"); //$NON-NLS-1$
// call.addChar("path", dir); //$NON-NLS-1$
// final RCharacterStore data= RDataUtils.checkRCharVector(call.evalData(monitor)).getData();
// files= data.toArray();
// }
//
// this.biocViews= views;
// this.biocViewsVersion= pkg.getVersion();
// this.biocViewsStamp= event.stamp;
// event.views= true;
//}
}