package edu.usc.cssl.tacit.crawlers.twitter.ui;
import java.io.File;
import java.io.IOException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.IMessageManager;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;
import edu.usc.cssl.tacit.common.ui.CommonUiActivator;
import edu.usc.cssl.tacit.common.ui.composite.from.TacitFormComposite;
import edu.usc.cssl.tacit.common.ui.outputdata.OutputLayoutData;
import edu.usc.cssl.tacit.common.ui.validation.OutputPathValidation;
import edu.usc.cssl.tacit.crawlers.twitter.services.TwitterStreamApi;
import edu.usc.cssl.tacit.crawlers.twitter.ui.internal.ITwitterCrawlerUIConstants;
import edu.usc.cssl.tacit.crawlers.twitter.ui.internal.TwitterCrawlerImageRegistry;
public class TwitterCrawlerView extends ViewPart implements
ITwitterCrawlerUIConstants {
public static final String ID = "edu.usc.cssl.tacit.crawlers.twitter.ui.view1";
private ScrolledForm form;
private FormToolkit toolkit;
private OutputLayoutData layoutData;
private static Text wordFilterText;
private static Text geoFilterText;
private static Button limitRecords;
private static Text dayText;
private static Text hourText;
private static Button maxLimit;
private static Text maxText;
private static Text minText;
private static Button userNameBtn;
private static Button favBtn;
private static Button reTweetBtn;
private static Button langBtn;
private static Button createdBtn;
private static Button textBtn;
private static Button statusIdBtn;
private static Button geoLocBtn;
private long finishTime;
private long maxTweetLimit;
private boolean noWordFilter;
private boolean noLocationFilter;
private boolean[] storedAtts;
private boolean validGeoFilter = true;
private boolean validLimitParse = true;
private boolean validLimitState = false;
private String keyWords[];
private double[][] geoLocations;
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
public void createPartControl(Composite parent) {
toolkit = new FormToolkit(parent.getDisplay());
form = toolkit.createScrolledForm(parent);
toolkit.decorateFormHeading(form.getForm());
form.setText("Twitter Crawler"); //$NON-NLS-1$
GridLayoutFactory.fillDefaults().applyTo(form.getBody());
Section section = toolkit.createSection(form.getBody(),
Section.TITLE_BAR | Section.EXPANDED);
GridDataFactory.fillDefaults().grab(true, false).span(1, 1)
.applyTo(section);
section.setExpanded(true);
ScrolledComposite sc = new ScrolledComposite(section, SWT.H_SCROLL
| SWT.V_SCROLL);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false)
.applyTo(sc);
TacitFormComposite.addErrorPopup(form.getForm(), toolkit);
// Output Data
Composite client1 = toolkit.createComposite(form.getBody());
GridLayoutFactory.fillDefaults().equalWidth(true).numColumns(2)
.applyTo(client1);
GridDataFactory.fillDefaults().grab(true, false).span(1, 1)
.applyTo(client1);
createFilterSection(toolkit, client1, form.getMessageManager());
createLimitSection(toolkit, client1, form.getMessageManager());
Label dummy = toolkit.createLabel(form.getBody(), "", SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).span(2, 0)
.applyTo(dummy);
createStoredAttributesSection(toolkit, form.getBody(),
form.getMessageManager());
Label filler = toolkit.createLabel(form.getBody(), "", SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).span(2, 0)
.applyTo(filler);
layoutData = TacitFormComposite.createOutputSection(toolkit,
form.getBody(), form.getMessageManager());
Composite outputSectionClient = layoutData.getSectionClient();
form.getForm().addMessageHyperlinkListener(new HyperlinkAdapter());
// form.setMessage("Invalid path", IMessageProvider.ERROR);
this.setPartName("Twitter Crawler");
IToolBarManager mgr = form.getToolBarManager();
mgr.add(new Action() {
@Override
public ImageDescriptor getImageDescriptor() {
return (TwitterCrawlerImageRegistry.getImageIconFactory()
.getImageDescriptor(IMAGE_LRUN_OBJ));
}
@Override
public String getToolTipText() {
return "Crawl";
}
public void run() {
TacitFormComposite.updateStatusMessage(getViewSite(), null,
null, form);
// Make sure input values are in valid state then launch
// streamer
noWordFilter = false;
noLocationFilter = false;
long dayLimit;
long hourLimit;
long minLimit;
// check limit tab attributes validity
if (limitRecords.getSelection()) {
try {
dayLimit = Long.parseLong(dayText.getText().toString());
hourLimit = Long.parseLong(hourText.getText()
.toString());
minLimit = Long.parseLong(minText.getText().toString());
// Is streaming time positive interger?
if (dayLimit < 0
|| hourLimit < 0
|| minLimit < 0
|| (dayLimit == 0 && hourLimit == 0 && minLimit == 0))
validLimitParse = false;
finishTime = (minLimit + (hourLimit + dayLimit * 24) * 60) * 1000 * 60;
} catch (NumberFormatException e1) {
validLimitParse = false;
}
}
// Is there valid max tweet number?
if (maxLimit.getSelection()) {
try {
maxTweetLimit = Long.parseLong(maxText.getText()
.toString());
if (maxTweetLimit <= 0)
validLimitParse = false;
} catch (NumberFormatException e1) {
validLimitParse = false;
}
}
// either maxTweet or maxTime must be activated
if (limitRecords.getSelection() || maxLimit.getSelection()) {
validLimitState = true;
}
// check if the output address is correct and writable
final String outputFile = layoutData.getOutputLabel().getText()
+ File.separator + "Twitter_Strem.txt";
storedAtts = new boolean[8];
// Get stored attribute values
storedAtts[0] = userNameBtn.getSelection();
storedAtts[1] = textBtn.getSelection();
storedAtts[2] = reTweetBtn.getSelection();
storedAtts[3] = geoLocBtn.getSelection();
storedAtts[4] = createdBtn.getSelection();
storedAtts[5] = favBtn.getSelection();
storedAtts[6] = statusIdBtn.getSelection();
storedAtts[7] = langBtn.getSelection();
final TwitterStreamApi ttStream = new TwitterStreamApi();
final boolean maxLimitEnabled = maxLimit.getSelection();
final boolean timeLimit = limitRecords.getSelection();
Job job = new Job("Twitter Stream Job") {
protected IStatus run(IProgressMonitor monitor) {
try {
TacitFormComposite.setConsoleViewInFocus();
TacitFormComposite.updateStatusMessage(
getViewSite(), null, null, form);
long totalJobWork = maxTweetLimit + 20;
if (maxTweetLimit == 0) {
totalJobWork = 200;
}
monitor.beginTask("Crawling Twitter ...",
(int) totalJobWork);
ttStream.stream(outputFile, maxLimitEnabled,
maxTweetLimit, timeLimit, finishTime,
noWordFilter, keyWords, noLocationFilter,
geoLocations, storedAtts, monitor);
monitor.done();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Status.OK_STATUS;
}
};
job.setUser(true);
if (canProceedCrawl())
job.schedule();
}
});
Action helpAction = new Action() {
@Override
public ImageDescriptor getImageDescriptor() {
return (TwitterCrawlerImageRegistry.getImageIconFactory()
.getImageDescriptor(IMAGE_HELP_CO));
}
@Override
public String getToolTipText() {
return "Help";
}
@Override
public void run() {
PlatformUI
.getWorkbench()
.getHelpSystem()
.displayHelp(
"edu.usc.cssl.tacit.crawlers.twitter.ui.twitter");
};
};
mgr.add(helpAction);
PlatformUI
.getWorkbench()
.getHelpSystem()
.setHelp(helpAction,
"edu.usc.cssl.tacit.crawlers.twitter.ui.twitter");
PlatformUI
.getWorkbench()
.getHelpSystem()
.setHelp(form, "edu.usc.cssl.tacit.crawlers.twitter.ui.twitter");
form.getToolBarManager().update(true);
toolkit.paintBordersFor(form.getBody());
}
private void createFilterSection(GridLayout layout, Composite parent) {
Section section = toolkit.createSection(parent, Section.TWISTIE
| Section.TITLE_BAR);
section.setActiveToggleColor(toolkit.getHyperlinkGroup()
.getActiveForeground());
section.setToggleColor(toolkit.getColors().getColor(
IFormColors.SEPARATOR));
FormText descriptionFrm = toolkit.createFormText(section, false);
descriptionFrm.setText("<form><p>" + "Filter settings" + "</p></form>",
true, false);
section.setDescriptionControl(descriptionFrm);
Composite client = toolkit.createComposite(section, SWT.WRAP);
client.setLayout(layout);
TacitFormComposite.createEmptyRow(toolkit, client);
ScrolledComposite pluginTabContainer = new ScrolledComposite(client,
SWT.H_SCROLL | SWT.V_SCROLL);
pluginTabContainer.setExpandHorizontal(true);
pluginTabContainer.setExpandVertical(true);
GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false)
.applyTo(pluginTabContainer);
Composite scInput = toolkit.createComposite(pluginTabContainer);
GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false)
.applyTo(scInput);
pluginTabContainer.setContent(scInput);
createAdditionalOptions(scInput);
Label dummyLb1 = toolkit.createLabel(scInput, "", SWT.NONE);
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(dummyLb1);
section.setText("tttt");
section.setDescription("<form><p>This section has a <b>tree</b> and a button. It also has <a>a link</a> in the description.</p></form>");
section.setClient(client);
section.setExpanded(true);
GridData gd = new GridData(GridData.FILL_BOTH);
section.setLayoutData(gd);
}
private void createAdditionalOptions(Composite sectionClient) {
Label noClusterTxtLbl = toolkit.createLabel(sectionClient,
"Number of clusters:", SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(noClusterTxtLbl);
Text noClusterTxt = toolkit.createText(sectionClient, "", SWT.BORDER);
noClusterTxt.setText("1");
GridDataFactory.fillDefaults().grab(true, false).span(2, 0)
.applyTo(noClusterTxt);
}
private boolean canProceedCrawl() {
TacitFormComposite.updateStatusMessage(getViewSite(), null, null, form);
boolean canProceed = true;
keyWords = wordFilterText.getText().split(";");
if (keyWords.length == 0 || wordFilterText.getText().isEmpty())
noWordFilter = true;
// check geofilter string validity
String geoWords[] = geoFilterText.getText().split(";");
geoLocations = new double[geoWords.length][2];
if ((geoWords.length % 2 == 1) && (geoWords.length != 1)) // check
// valid
// number
// of
// pairs
validGeoFilter = false;
else {
for (int i = 0; i < geoWords.length
&& !geoFilterText.getText().isEmpty(); i++) {
String geoTemp[] = geoWords[i].split(",");
if (geoTemp.length != 2) // check if there are only two
// values in the pair
validGeoFilter = false;
else {
if (geoTemp[0].isEmpty() || geoTemp[1].isEmpty())
validGeoFilter = false; // check if there is
// something to be read
else {
try { // check if there is a valid number
geoLocations[i][0] = Double.parseDouble(geoTemp[0]);
geoLocations[i][1] = Double.parseDouble(geoTemp[1]);
} catch (NumberFormatException e2) {
validGeoFilter = false;
}
}
}
}
}
// is there any geofilter?
if (geoLocations.length == 0 || geoFilterText.getText().isEmpty())
noLocationFilter = true;
form.getMessageManager().removeMessage("location");
form.getMessageManager().removeMessage("geolocation");
form.getMessageManager().removeMessage("limit");
form.getMessageManager().removeMessage("state");
String message = OutputPathValidation.getInstance()
.validateOutputDirectory(layoutData.getOutputLabel().getText(),
"Output");
if (message != null) {
message = layoutData.getOutputLabel().getText() + " " + message;
form.getMessageManager().addMessage("location", message, null,
IMessageProvider.ERROR);
canProceed = false;
}
// first check if everything works then stream
String userName = CommonUiActivator.getDefault().getPreferenceStore()
.getString("user");
if (userName.length() == 0) {
ErrorDialog.openError(Display.getDefault().getActiveShell(),
"User name is not configured",
"Please check user settings for Twitter", new Status(
IStatus.ERROR, CommonUiActivator.PLUGIN_ID,
"No/Valid user is not found"));
String id = "edu.usc.cssl.tacit.crawlers.twitter.ui.userconfig";
PreferencesUtil.createPreferenceDialogOn(
Display.getDefault().getActiveShell(), id,
new String[] { id }, null).open();
canProceed = false;
} else if (!validGeoFilter) {
form.getMessageManager()
.addMessage(
"geolocation",
"Error: Invalid gelocation query. Please compare with example.",
null, IMessageProvider.ERROR);
canProceed = false;
} else if (!validLimitParse) {
form.getMessageManager()
.addMessage(
"limit",
"Error: Invalid parsing. Please makes sure all enabled fields are positive discrete numbers.",
null, IMessageProvider.ERROR);
canProceed = false;
} else if (!validLimitState) {
form.getMessageManager().addMessage("state",
"Error: Select atleaset Maximum limit or Time limit",
null, IMessageProvider.ERROR);
canProceed = false;
}
return canProceed;
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
form.setFocus();
}
public static void createFilterSection(FormToolkit toolkit,
Composite parent, final IMessageManager mmng) {
Section section = toolkit.createSection(parent, Section.TITLE_BAR
| Section.EXPANDED | Section.DESCRIPTION | Section.TWISTIE);
GridDataFactory.fillDefaults().grab(true, false).span(1, 1)
.applyTo(section);
GridLayoutFactory.fillDefaults().numColumns(3).applyTo(section);
section.setText("Filter Settings "); //$NON-NLS-1$
section.setDescription("Choose values for Filter");
ScrolledComposite sc = new ScrolledComposite(section, SWT.H_SCROLL
| SWT.V_SCROLL);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false)
.applyTo(sc);
Composite sectionClient = toolkit.createComposite(section);
sc.setContent(sectionClient);
GridDataFactory.fillDefaults().grab(true, false).applyTo(sc);
GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false)
.applyTo(sectionClient);
section.setClient(sectionClient);
TacitFormComposite.createEmptyRow(toolkit, sectionClient);
final Label wordFilterLbl = toolkit.createLabel(sectionClient,
"Word Filter", SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(wordFilterLbl);
wordFilterText = toolkit.createText(sectionClient, "", SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(wordFilterText);
final Label geoFilterLbl = toolkit.createLabel(sectionClient,
"Geo Filter", SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(geoFilterLbl);
geoFilterText = toolkit.createText(sectionClient, "", SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(geoFilterText);
}
public static void createLimitSection(FormToolkit toolkit,
Composite parent, final IMessageManager mmng) {
Section section = toolkit.createSection(parent, Section.TITLE_BAR
| Section.EXPANDED | Section.DESCRIPTION | Section.TWISTIE);
GridDataFactory.fillDefaults().grab(true, false).span(1, 1)
.applyTo(section);
GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false)
.applyTo(section);
section.setText("Limit Tweets"); //$NON-NLS-1$
section.setDescription("Limit number of tweets crawled based on following settings");
ScrolledComposite sc = new ScrolledComposite(section, SWT.H_SCROLL
| SWT.V_SCROLL);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
GridLayoutFactory.fillDefaults().numColumns(6).equalWidth(false)
.applyTo(sc);
Composite sectionClient = toolkit.createComposite(section);
sc.setContent(sectionClient);
GridDataFactory.fillDefaults().grab(true, false).applyTo(sc);
GridLayoutFactory.fillDefaults().numColumns(6).equalWidth(false)
.applyTo(sectionClient);
section.setClient(sectionClient);
TacitFormComposite.createEmptyRow(toolkit, sectionClient);
TacitFormComposite.createEmptyRow(toolkit, sectionClient);
limitRecords = new Button(sectionClient, SWT.CHECK);
limitRecords.setText("Time Limit");
GridDataFactory.fillDefaults().grab(false, false).span(6, 0)
.applyTo(limitRecords);
Composite maxClient = toolkit.createComposite(sectionClient);
GridDataFactory.fillDefaults().grab(true, false).applyTo(maxClient);
GridLayoutFactory.fillDefaults().numColumns(6).equalWidth(false)
.applyTo(maxClient);
final Label dayLabel = new Label(maxClient, SWT.NONE);
dayLabel.setText("Days :");
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(dayLabel);
dayText = toolkit.createText(maxClient, "", SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(dayText);
final Label hourLbl = new Label(maxClient, SWT.NONE);
hourLbl.setText("Hours :");
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(hourLbl);
hourText = toolkit.createText(maxClient, "", SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(hourText);
final Label minLbl = new Label(maxClient, SWT.NONE);
minLbl.setText("Minutes :");
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(minLbl);
minText = toolkit.createText(maxClient, "", SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(minText);
// MAX Tweet area
maxLimit = new Button(maxClient, SWT.CHECK);
maxLimit.setText("Maximum Limit");
GridDataFactory.fillDefaults().grab(false, false).span(1, 0)
.applyTo(maxLimit);
maxText = toolkit.createText(maxClient, "", SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(5, 0)
.applyTo(maxText);
limitRecords.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (limitRecords.getSelection()) {
dayText.setEnabled(true);
dayText.setEditable(true);
hourText.setEnabled(true);
hourText.setEditable(true);
minText.setEnabled(true);
minText.setEditable(true);
} else {
dayText.setEnabled(false);
dayText.setEditable(false);
hourText.setEnabled(false);
hourText.setEditable(false);
minText.setEnabled(false);
minText.setEditable(false);
}
}
});
maxLimit.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (maxLimit.getSelection()) {
maxText.setEnabled(true);
maxText.setEditable(true);
} else {
maxText.setEnabled(false);
maxText.setEditable(false);
}
}
});
}
public static void createStoredAttributesSection(FormToolkit toolkit,
Composite parent, final IMessageManager mmng) {
Section section = toolkit.createSection(parent, Section.TITLE_BAR
| Section.EXPANDED | Section.DESCRIPTION | Section.TWISTIE);
GridDataFactory.fillDefaults().grab(true, false).span(1, 1)
.applyTo(section);
GridLayoutFactory.fillDefaults().numColumns(4).applyTo(section);
section.setText("Stored Attributes "); //$NON-NLS-1$
section.setDescription("Choose values for Filter");
ScrolledComposite sc = new ScrolledComposite(section, SWT.H_SCROLL
| SWT.V_SCROLL);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
GridLayoutFactory.fillDefaults().numColumns(4).equalWidth(false)
.applyTo(sc);
Composite sectionClient = toolkit.createComposite(section);
sc.setContent(sectionClient);
GridDataFactory.fillDefaults().grab(true, false).applyTo(sc);
GridLayoutFactory.fillDefaults().numColumns(4).equalWidth(false)
.applyTo(sectionClient);
section.setClient(sectionClient);
Label dummy = toolkit.createLabel(sectionClient, "", SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).span(4, 0)
.applyTo(dummy);
userNameBtn = new Button(sectionClient, SWT.CHECK);
userNameBtn.setText("User Name");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(userNameBtn);
geoLocBtn = new Button(sectionClient, SWT.CHECK);
geoLocBtn.setText("Geo Location");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(geoLocBtn);
statusIdBtn = new Button(sectionClient, SWT.CHECK);
statusIdBtn.setText("Status Id");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(statusIdBtn);
textBtn = new Button(sectionClient, SWT.CHECK);
textBtn.setText("Text");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(textBtn);
createdBtn = new Button(sectionClient, SWT.CHECK);
createdBtn.setText("Created at");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(createdBtn);
langBtn = new Button(sectionClient, SWT.CHECK);
langBtn.setText("Language");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(langBtn);
reTweetBtn = new Button(sectionClient, SWT.CHECK);
reTweetBtn.setText("Re-tweet Number ");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(reTweetBtn);
favBtn = new Button(sectionClient, SWT.CHECK);
favBtn.setText("Favorite Count");
GridDataFactory.fillDefaults().grab(true, false).span(1, 0)
.applyTo(favBtn);
}
}