/**
* Copyright (c) 2015 Pawel Nowak.
* 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
*/
package org.eclipse.recommenders.internal.news.rcp.preferences;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.List;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.recommenders.internal.news.rcp.CommonImages;
import org.eclipse.recommenders.internal.news.rcp.Constants;
import org.eclipse.recommenders.internal.news.rcp.FeedDescriptor;
import org.eclipse.recommenders.internal.news.rcp.l10n.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
public class FeedDialog extends TitleAreaDialog {
@VisibleForTesting
static final List<String> ACCEPTED_PROTOCOLS = ImmutableList.of("http", "https"); //$NON-NLS-1$ , //$NON-NLS-2$
private final List<FeedDescriptor> existingDescriptors;
private FeedDescriptor feed;
private Text nameValue;
private Text urlValue;
private Text pollingIntervalValue;
public FeedDialog(Shell parentShell, List<FeedDescriptor> existingDescriptors) {
this(parentShell, null, existingDescriptors);
}
public FeedDialog(Shell parentShell, FeedDescriptor feed, List<FeedDescriptor> existingDescriptors) {
super(parentShell);
this.feed = feed;
this.existingDescriptors = existingDescriptors;
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
if (feed != null) {
newShell.setText(Messages.FEED_DIALOG_TITLE_EDIT);
} else {
newShell.setText(Messages.FEED_DIALOG_TITLE_NEW);
}
}
@Override
public void create() {
super.create();
if (feed != null) {
setTitle(Messages.FEED_DIALOG_TITLE_EDIT);
} else {
setTitle(Messages.FEED_DIALOG_TITLE_NEW);
}
setMessage(Messages.FEED_DIALOG_DESCRIPTION);
setHelpAvailable(false);
setTitleImage(CommonImages.RSS_DIALOG_TITLE.createImage());
super.getButton(OK).setEnabled(false);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite area = (Composite) super.createDialogArea(parent);
Composite container = new Composite(area, SWT.NONE);
container.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout(2, false);
container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
container.setLayout(layout);
createFeed(container);
Dialog.applyDialogFont(area);
return area;
}
private void createFeed(Composite container) {
GridData gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.horizontalAlignment = GridData.FILL;
String nameInputValue = ""; //$NON-NLS-1$
String urlInputValue = ""; //$NON-NLS-1$
String pollingIntervalInputValue = String.valueOf(Constants.DEFAULT_POLLING_INTERVAL);
if (feed != null) {
nameInputValue = feed.getName();
urlInputValue = feed.getUri().toString();
pollingIntervalInputValue = Long.toString(feed.getPollingInterval());
}
nameValue = createLabelInputFieldPair(container, gridData, nameValue, Messages.FIELD_LABEL_FEED_NAME,
nameInputValue);
urlValue = createLabelInputFieldPair(container, gridData, urlValue, Messages.FIELD_LABEL_URL, urlInputValue);
pollingIntervalValue = createLabelInputFieldPair(container, gridData, pollingIntervalValue,
Messages.FIELD_LABEL_POLLING_INTERVAL, pollingIntervalInputValue);
pollingIntervalValue.setTextLimit(4);
addModifyListeners(nameValue, urlValue, pollingIntervalValue);
}
private Text createLabelInputFieldPair(Composite container, GridData gridData, Text text, String labelText,
String inputValue) {
Label label = new Label(container, SWT.NONE);
label.setText(labelText);
text = new Text(container, SWT.BORDER);
text.setText(inputValue);
text.setLayoutData(gridData);
return text;
}
private void addModifyListeners(Text... texts) {
ModifyListener validateDialog = new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
updateDialog();
}
};
for (Text text : texts) {
text.addModifyListener(validateDialog);
}
}
@Override
protected boolean isResizable() {
return false;
}
@Override
protected void okPressed() {
feed = new FeedDescriptor(urlValue.getText(), nameValue.getText(), parsePollingIntervalQuietly(pollingIntervalValue.getText()).or(0L));
super.okPressed();
}
public FeedDescriptor getFeed() {
return feed;
}
private void updateDialog() {
setErrorMessage(validateFeedDialog(feed, nameValue.getText(), urlValue.getText(),
pollingIntervalValue.getText(), existingDescriptors));
if (getErrorMessage() == null) {
super.getButton(OK).setEnabled(true);
} else {
super.getButton(OK).setEnabled(false);
}
}
@VisibleForTesting
static String validateFeedDialog(FeedDescriptor currentFeed, String name, String url, String pollingInterval,
List<FeedDescriptor> existingDescriptors) {
FeedDescriptor duplicateFeed = getFeedWithDuplicateUrl(url, currentFeed, existingDescriptors).orNull();
URI feedUri = parseUriQuietly(url).orNull();
if (Strings.isNullOrEmpty(name)) {
return Messages.FEED_DIALOG_ERROR_EMPTY_NAME;
} else if (Strings.isNullOrEmpty(url)) {
return Messages.FEED_DIALOG_ERROR_EMPTY_URL;
} else if (feedUri == null || !feedUri.isAbsolute()) {
return Messages.FEED_DIALOG_ERROR_INVALID_URL;
} else if (!isUriProtocolSupported(feedUri, ACCEPTED_PROTOCOLS)) {
return MessageFormat.format(Messages.FEED_DIALOG_ERROR_PROTOCOL_UNSUPPORTED, url,
Joiner.on(", ").join(ACCEPTED_PROTOCOLS)); //$NON-NLS-1$
} else if (duplicateFeed != null) {
return MessageFormat.format(Messages.FEED_DIALOG_ERROR_DUPLICATE_FEED, duplicateFeed.getName());
} else if (!parsePollingIntervalQuietly(pollingInterval).isPresent()) {
return Messages.FEED_DIALOG_ERROR_POLLING_INTERVAL_INVALID;
}
return null;
}
private static Optional<URI> parseUriQuietly(String uriString) {
try {
return Optional.of(new URI(uriString));
} catch (URISyntaxException e) {
return Optional.absent();
}
}
private static Optional<Long> parsePollingIntervalQuietly(String longString) {
try {
long pollingInterval = Long.parseLong(longString);
if (pollingInterval > 0) {
return Optional.of(pollingInterval);
} else {
return Optional.absent();
}
} catch (NumberFormatException e) {
return Optional.absent();
}
}
private static boolean isUriProtocolSupported(URI uri, List<String> protocols) {
if (uri == null) {
return false;
}
for (String protocol : protocols) {
if (protocol.equalsIgnoreCase(uri.getScheme()) || protocol.equalsIgnoreCase(uri.toString())) {
return true;
}
}
return false;
}
private static Optional<FeedDescriptor> getFeedWithDuplicateUrl(String url, FeedDescriptor feed,
List<FeedDescriptor> descriptors) {
for (FeedDescriptor compare : descriptors) {
if (feed == compare) {
continue;
}
if (url.equals(compare.getUri().toString())) {
return Optional.of(compare);
}
}
return Optional.absent();
}
}