blob: d33ac787b950351b6b76b5e010110218d242d8fb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.uima.ruta.ide.ui.documentation;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.uima.internal.util.XMLUtils;
import org.apache.uima.ruta.ide.ui.RutaPreferenceConstants;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.ui.DLTKPluginImages;
import org.eclipse.dltk.ui.dialogs.TimeTriggeredProgressMonitorDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class RutaPagesLocationsBlock implements SelectionListener, ISelectionChangedListener {
protected static final String LAST_PATH_SETTING = "LAST_PATH_SETTING"; //$NON-NLS-1$
protected static final String DIALOG_SETTINGS_PREFIX = "RutaPagesLocationsBlock"; //$NON-NLS-1$
protected boolean fInCallback = false;
protected File fHome;
// widgets
protected TreeViewer fLocationsViewer;
private Button fClearButton;
private Button fRemoveButton;
private Button fAddButton;
protected Button fDefaultButton;
private ManLocationsContentProvider fLocationsContentProvider;
private PreferencePage fPage;
private IPreferenceStore fStore;
public RutaPagesLocationsBlock(IPreferenceStore store, PreferencePage page) {
fPage = page;
fStore = store;
}
protected IBaseLabelProvider getLabelProvider() {
return new LabelProvider() {
@Override
public Image getImage(Object element) {
if (element instanceof RutaPageFolder) {
return DLTKPluginImages.DESC_OBJS_LIBRARY.createImage();
}
return DLTKPluginImages.DESC_OBJS_INFO_OBJ.createImage();
}
@Override
public String getText(Object element) {
if (element instanceof RutaPageFolder) {
RutaPageFolder folder = (RutaPageFolder) element;
return folder.getPath();
}
return super.getText(element);
}
};
}
private List folders = null;
private String getFoldersAsXML() {
if (folders == null)
return null;
// Create the Document and the top-level node
DocumentBuilderFactory documentBuilderFactory = XMLUtils.createDocumentBuilderFactory();
DocumentBuilder builder;
try {
builder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
return null;
}
Document doc = builder.newDocument();
Element topElement = doc.createElement("manPages");
doc.appendChild(topElement);
for (Iterator iterator = folders.iterator(); iterator.hasNext();) {
RutaPageFolder f = (RutaPageFolder) iterator.next();
Element location = doc.createElement("location");
topElement.appendChild(location);
location.setAttribute("path", f.getPath());
for (Iterator iterator2 = f.getPages().keySet().iterator(); iterator2.hasNext();) {
String name = (String) iterator2.next();
String file = (String) f.getPages().get(name);
Element page = doc.createElement("page");
location.appendChild(page);
page.setAttribute("keyword", name);
page.setAttribute("file", file);
}
}
ByteArrayOutputStream s = new ByteArrayOutputStream();
try {
TransformerFactory factory = XMLUtils.createTransformerFactory();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource source = new DOMSource(doc);
StreamResult outputTarget = new StreamResult(s);
transformer.transform(source, outputTarget);
} catch (TransformerException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
String result = null;
try {
result = s.toString("UTF8");
} catch (UnsupportedEncodingException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
return result;
}
private class ManLocationsContentProvider implements ITreeContentProvider {
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof RutaPageFolder) {
RutaPageFolder folder = (RutaPageFolder) parentElement;
String[] ch = new String[folder.getPages().size()];
int i = 0;
for (Iterator iterator = folder.getPages().keySet().iterator(); iterator.hasNext();) {
String kw = (String) iterator.next();
String file = (String) folder.getPages().get(kw);
ch[i++] = kw + " (" + file + ")";
}
return ch;
}
return new Object[0];
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof RutaPageFolder)
return true;
return false;
}
@Override
public Object[] getElements(Object inputElement) {
if (folders == null)
return new Object[0];
return folders.toArray(new Object[folders.size()]);
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
/**
* Creates and returns the source lookup control.
*
* @param parent
* the parent widget of this control
*/
public Control createControl(Composite parent) {
Font font = parent.getFont();
Composite comp = new Composite(parent, SWT.NONE);
GridLayout topLayout = new GridLayout();
topLayout.numColumns = 2;
topLayout.marginHeight = 0;
topLayout.marginWidth = 0;
comp.setLayout(topLayout);
GridData gd = new GridData(GridData.FILL_BOTH);
comp.setLayoutData(gd);
fLocationsViewer = new TreeViewer(comp);
gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 6;
fLocationsViewer.getControl().setLayoutData(gd);
fLocationsContentProvider = new ManLocationsContentProvider();
fLocationsViewer.setSorter(new ViewerSorter());
fLocationsViewer.setContentProvider(fLocationsContentProvider);
fLocationsViewer.setLabelProvider(getLabelProvider());
fLocationsViewer.setInput(this);
fLocationsViewer.addSelectionChangedListener(this);
Composite pathButtonComp = new Composite(comp, SWT.NONE);
GridLayout pathButtonLayout = new GridLayout();
pathButtonLayout.marginHeight = 0;
pathButtonLayout.marginWidth = 0;
pathButtonComp.setLayout(pathButtonLayout);
gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL);
pathButtonComp.setLayoutData(gd);
pathButtonComp.setFont(font);
fAddButton = createPushButton(pathButtonComp, "Add folder...");
fAddButton.addSelectionListener(this);
fRemoveButton = createPushButton(pathButtonComp, "Remove");
fRemoveButton.addSelectionListener(this);
fClearButton = createPushButton(pathButtonComp, "Remove All");
fClearButton.addSelectionListener(this);
return comp;
}
/**
* Creates and returns a button
*
* @param parent
* parent widget
* @param label
* label
* @return Button
*/
protected Button createPushButton(Composite parent, String label) {
Button button = new Button(parent, SWT.PUSH);
button.setFont(parent.getFont());
button.setText(label);
setButtonLayoutData(button);
return button;
}
protected void setButtonLayoutData(Button button) {
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
int widthHint = 80;
Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
data.widthHint = Math.max(widthHint, minSize.x);
button.setLayoutData(data);
}
/**
* Create some empty space
*/
protected void createVerticalSpacer(Composite comp, int colSpan) {
Label label = new Label(comp, SWT.NONE);
GridData gd = new GridData();
gd.horizontalSpan = colSpan;
label.setLayoutData(gd);
}
/**
* Updates buttons and status based on current mans
*/
public void update() {
updateButtons();
if (folders != null) {
for (Iterator iterator = folders.iterator(); iterator.hasNext();) {
RutaPageFolder v = (RutaPageFolder) iterator.next();
if (!v.verify()) {
iterator.remove();
}
}
}
fLocationsViewer.refresh();
updatePageStatus(Status.OK_STATUS);
}
public void setDefaults() {
String res = fStore.getDefaultString(RutaPreferenceConstants.DOC_RUTA_PAGES_LOCATIONS);
fStore.setValue(RutaPreferenceConstants.DOC_RUTA_PAGES_LOCATIONS, res);
initialize();
}
protected void updatePageStatus(IStatus status) {
if (fPage == null)
return;
fPage.setValid(status.isOK());
if (!status.isOK())
fPage.setErrorMessage(status.getMessage());
else
fPage.setErrorMessage(null);
}
public void initialize() {
String value = fStore.getString(RutaPreferenceConstants.DOC_RUTA_PAGES_LOCATIONS);
try {
this.folders = RutaPageFolder.readXML(value);
} catch (IOException e) {
e.printStackTrace();
}
update();
}
/**
* Saves settings
*/
public void performApply() {
String xml = this.getFoldersAsXML();
if (xml != null)
fStore.setValue(RutaPreferenceConstants.DOC_RUTA_PAGES_LOCATIONS, xml);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
Object source = e.getSource();
if (source == fClearButton) {
folders.clear();
} else if (source == fRemoveButton) {
IStructuredSelection selection = (IStructuredSelection) fLocationsViewer.getSelection();
Object[] array = selection.toArray();
for (int i = 0; i < array.length; i++) {
if (array[i] instanceof RutaPageFolder) {
for (Iterator iterator = folders.iterator(); iterator.hasNext();) {
RutaPageFolder f = (RutaPageFolder) iterator.next();
if (f == array[i]) {
iterator.remove();
break;
}
}
}
}
} else if (source == fAddButton) {
add();
}
update();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.
* SelectionEvent)
*/
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
/**
* Open the file selection dialog, and add the return locations.
*/
protected void add() {
DirectoryDialog dialog = new DirectoryDialog(fLocationsViewer.getControl().getShell());
dialog.setMessage("Select directory to search into");
String result = dialog.open();
if (result != null) {
final File file = new File(result);
if (this.folders == null)
this.folders = new ArrayList();
if (file != null && file.isDirectory()) {
ProgressMonitorDialog dialog2 = new TimeTriggeredProgressMonitorDialog(null, 500);
try {
dialog2.run(true, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
monitor.beginTask("Searching for man pages", 1);
performSearch(file);
monitor.done();
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void performSearch(File dir) {
if (!dir.isDirectory())
return;
String name = dir.getName();
if (name.equals("TkLib") || name.equals("RutaLib") || name.equals("Keywords")
|| name.equals("UserCmd"))
return;
File[] childs = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isDirectory())
return true;
if (file.getName().startsWith("contents.htm"))
return true;
return false;
}
});
for (int i = 0; i < childs.length; i++) {
if (childs[i].isDirectory()) {
performSearch(childs[i]);
}
if (childs[i].getName().startsWith("contents.htm")) {
RutaPageFolder folder = new RutaPageFolder(dir.getAbsolutePath());
parseContentsFile(childs[i], folder);
if (folder.getPages().size() > 0 && !folders.contains(folder)) {
this.folders.add(folder);
}
}
}
}
private void parseContentsFile(File c, RutaPageFolder folder) {
FileReader reader;
try {
reader = new FileReader(c);
} catch (FileNotFoundException e) {
return;
}
StringBuffer buf = new StringBuffer();
while (true) {
char cbuf[] = new char[1024];
try {
int read = reader.read(cbuf);
if (read >= 0) {
buf.append(cbuf, 0, read);
} else
break;
} catch (IOException e) {
break;
}
}
String result = buf.toString();
Pattern pattern = Pattern.compile("<a\\s+href=\"([a-zA-Z_0-9]+\\.html?)\"\\s*>(\\w+)</a>",
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(result);
while (matcher.find()) {
String file = matcher.group(1);
if (file.equalsIgnoreCase("Copyright.htm"))
continue;
String word = matcher.group(2);
folder.addPage(word, file);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers
* .SelectionChangedEvent)
*/
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateButtons();
}
/**
* Refresh the enable/disable state for the buttons.
*/
private void updateButtons() {
fClearButton.setEnabled(folders != null && folders.size() > 0);
IStructuredSelection selection = (IStructuredSelection) fLocationsViewer.getSelection();
boolean canRemove = true;
if (folders == null)
canRemove = false;
else {
List list = selection.toList();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object o = iterator.next();
if (!folders.contains(o))
canRemove = false;
break;
}
if (selection.isEmpty())
canRemove = false;
}
fRemoveButton.setEnabled(canRemove);
}
}