/*******************************************************************************
* Copyright (c) 2011-2014 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.cdi.ui.wizard;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
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.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
import org.jboss.tools.cdi.core.CDICorePlugin;
import org.jboss.tools.cdi.core.CDIImages;
import org.jboss.tools.cdi.core.IBean;
import org.jboss.tools.cdi.core.ICDIProject;
import org.jboss.tools.cdi.core.util.BeanPresentationUtil;
import org.jboss.tools.cdi.internal.core.event.CDIProjectChangeEvent;
import org.jboss.tools.cdi.internal.core.event.ICDIProjectChangeListener;
import org.jboss.tools.cdi.ui.CDIUIMessages;
import org.jboss.tools.cdi.ui.CDIUIPlugin;
/**
* Open CDI Named Bean Dialog
*
* @author Victor V. Rubezhny
*/
public class OpenCDINamedBeanDialog extends FilteredItemsSelectionDialog {
private static final String FILE_NAME = "OpenCDINamedBeanHistory.xml"; //$NON-NLS-1$
private static final String ROOT_NODE = "historyRootNode"; //$NON-NLS-1$
private static final String INFO_NODE = "infoNode"; //$NON-NLS-1$
private static final String PROJECT_NAME = "ProjectName"; //$NON-NLS-1$
private static final String BEAN_NAME = "BeanName"; //$NON-NLS-1$
private static final String DELETED = "Deleted"; //$NON-NLS-1$
private static final String YES = "yes"; //$NON-NLS-1$
private static final String NO = "no"; //$NON-NLS-1$
public OpenCDINamedBeanDialog(Shell shell) {
this(shell, false);
}
public OpenCDINamedBeanDialog(Shell shell, boolean disableHistory) {
super(shell);
if (!disableHistory)
setSelectionHistory(new CDINamedBeanSelectionHistory());
setListLabelProvider(new CDINamedBeanLabelProvider());
setDetailsLabelProvider(new CDINamedBeanLabelProvider());
}
private final static ICDIProjectChangeListener cdiProjectListener =
new ICDIProjectChangeListener() {
public void projectChanged(CDIProjectChangeEvent event) {
validateHistory(event.getProject());
}
};
@Override
public boolean close() {
CDICorePlugin.removeCDIProjectListener(cdiProjectListener);
return super.close();
}
@Override
public int open() {
if (getSelectionHistory() != null) {
XMLMemento memento = loadMemento();
if (memento != null) {
getSelectionHistory().load(memento);
updateHistory(memento);
saveMemento(memento);
}
CDICorePlugin.addCDIProjectListener(cdiProjectListener);
}
return super.open();
}
private static void updateHistory(XMLMemento memento) {
XMLMemento historyMemento = (XMLMemento) memento
.getChild(ROOT_NODE);
if (historyMemento == null)
return;
IMemento[] mementoElements = historyMemento.getChildren(INFO_NODE);
for (int i = 0; i < mementoElements.length; ++i) {
IMemento mem = mementoElements[i];
String projectName = mem.getString(PROJECT_NAME);
if (projectName == null) {
mem.putString(DELETED, YES);
continue;
}
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
ICDIProject cdiProject = CDICorePlugin.getCDIProject(project, true);
if (cdiProject == null) {
mem.putString(DELETED, YES);
continue;
}
validateHistory(cdiProject, memento);
}
}
public void startSearch() {
applyFilter();
}
@Override
public void okPressed() {
// TODO Auto-generated method stub
super.okPressed();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public void stopSearchAndShowResults() {
refresh();
List list = getSelectedItems().toList();
Collections.sort(list,getItemsComparator());
setResult(list);
}
protected Control createExtendedContentArea(Composite parent) {
return null;
}
protected ItemsFilter createFilter() {
return new CDINamedBeanFilter();
}
protected void fillContentProvider(AbstractContentProvider contentProvider,
ItemsFilter itemsFilter, IProgressMonitor progressMonitor)
throws CoreException {
progressMonitor.subTask(CDIUIMessages.OPEN_CDI_NAMED_BEAN_DIALOG_WAIT);
try {
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);
} catch (InterruptedException e) {
// do nothing
}
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
.getProjects();
progressMonitor.beginTask(
CDIUIMessages.OPEN_CDI_NAMED_BEAN_DIALOG_LOADING,
projects.length);
for (IProject project : projects) {
progressMonitor.subTask(project.getName());
ICDIProject cdiProject = CDICorePlugin.getCDIProject(project, true);
if (cdiProject != null) {
for (IBean bean: cdiProject.getNamedBeans(false)) {
if (cdiProject == bean.getDeclaringProject()) {
contentProvider.add(new CDINamedBeanWrapper(bean
.getName(), project.getName(), bean),
itemsFilter);
}
}
}
progressMonitor.worked(1);
}
progressMonitor.done();
}
private static XMLMemento loadMemento() {
XMLMemento memento = null;
IPath stateLocation = CDIUIPlugin.getDefault().getStateLocation()
.append(FILE_NAME);
File file = new File(stateLocation.toOSString());
if (file.exists()) {
FileReader reader = null;
try {
reader = new FileReader(file);
memento = XMLMemento.createReadRoot(reader);
} catch (IOException ex) {
CDICorePlugin.getDefault().logError(ex);
} catch (WorkbenchException ex) {
CDICorePlugin.getDefault().logError(ex);
} finally {
try {
reader.close();
} catch (IOException ex) {
CDICorePlugin.getDefault().logError(ex);
}
}
}
return memento;
}
private static void saveMemento(XMLMemento xmlMemento) {
IPath stateLocation = CDIUIPlugin.getDefault().getStateLocation()
.append(FILE_NAME);
File file = new File(stateLocation.toOSString());
FileWriter writer = null;
try {
writer = new FileWriter(file);
xmlMemento.save(writer);
} catch (IOException ex) {
CDICorePlugin.getDefault().logError(ex);
} finally {
try {
writer.close();
} catch (IOException ex) {
CDICorePlugin.getDefault().logError(ex);
}
}
}
protected IDialogSettings getDialogSettings() {
return new DialogSettings(
CDIUIMessages.OPEN_CDI_NAMED_BEAN_DIALOG_NAME);
}
public String getElementName(Object item) {
if (item instanceof CDINamedBeanWrapper) {
CDINamedBeanWrapper beanWrapper = (CDINamedBeanWrapper) item;
return beanWrapper.getBeanName();
}
return null;
}
protected Comparator<CDINamedBeanWrapper> getItemsComparator() {
return new CDINamedBeanComparator();
}
protected IStatus validateItem(Object item) {
return new Status(getSelectedItems().size() >= 0?IStatus.OK:IStatus.ERROR,CDIUIPlugin.PLUGIN_ID,null);
}
public class CDINamedBeanComparator implements
Comparator<CDINamedBeanWrapper> {
public int compare(CDINamedBeanWrapper left, CDINamedBeanWrapper right) {
return left.getBeanName().compareTo(right.getBeanName());
}
}
public class CDINamedBeanFilter extends ItemsFilter {
public boolean isConsistentItem(Object item) {
if (item instanceof CDINamedBeanWrapper) {
CDINamedBeanWrapper beanWrapper = (CDINamedBeanWrapper) item;
String projectName = beanWrapper.getProjectName();
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
ICDIProject cdiProject = CDICorePlugin.getCDIProject(project, true);
if (cdiProject == null) {
return false;
}
String beanName = beanWrapper.getBeanName();
Collection<IBean> beans = cdiProject
.getBeans(beanName, true);
IBean bean = (beans == null || beans.isEmpty() ? null : beans.iterator().next());
return (bean != null);
}
return false;
}
public boolean matchItem(Object item) {
if (item instanceof CDINamedBeanWrapper) {
CDINamedBeanWrapper beanWrapper = (CDINamedBeanWrapper) item;
boolean result = patternMatcher.matches(beanWrapper
.getBeanName());
if (!result) {
String pattern = patternMatcher.getPattern();
if (pattern.indexOf(".") < 0) {
int lastIndex = beanWrapper.getBeanName()
.lastIndexOf(".");
if (lastIndex >= 0
&& (lastIndex + 1) < beanWrapper
.getBeanName().length())
return patternMatcher.matches(beanWrapper
.getBeanName()
.substring(lastIndex + 1));
}
}
return result;
}
return false;
}
}
public class CDINamedBeanSelectionHistory extends SelectionHistory {
public CDINamedBeanSelectionHistory() {
super();
}
protected Object restoreItemFromMemento(IMemento memento) {
XMLMemento mem = (XMLMemento) memento;
String projectName = mem.getString(PROJECT_NAME);
if (projectName == null)
return null;
String beanName = mem.getString(BEAN_NAME);
if (beanName == null)
return null;
String beanDeleted = mem.getString(DELETED);
if (beanDeleted != null && YES.equals(beanDeleted))
return null;
return new CDINamedBeanWrapper(beanName, projectName);
}
@Override
protected void storeItemToMemento(Object item, IMemento memento) {
CDINamedBeanWrapper beanWrapper = (CDINamedBeanWrapper) item;
XMLMemento mem = (XMLMemento) memento;
mem.putString(PROJECT_NAME, beanWrapper.getProjectName());
mem.putString(BEAN_NAME, beanWrapper.getBeanName());
}
public void save(IMemento memento) {
super.save(memento);
if (!(memento instanceof XMLMemento))
return;
XMLMemento xmlMemento = (XMLMemento) memento;
saveMemento(xmlMemento);
}
}
private class CDIBeanStyler extends Styler {
private final Color foreground;
private final boolean bold;
private Font fBoldFont;
public CDIBeanStyler(boolean bold) {
this(null, bold);
}
public CDIBeanStyler(Color foreground) {
this(foreground, false);
}
public CDIBeanStyler(Color foreground, boolean bold) {
this.foreground = foreground;
this.bold = bold;
}
public void applyStyles(TextStyle textStyle) {
if (foreground != null) {
textStyle.foreground = foreground;
}
if (bold) {
textStyle.font= getBoldFont();
}
}
/**
* Create the bold variant of the currently used font.
*
* @return the bold font
* @since 3.5
*/
private Font getBoldFont() {
if (fBoldFont == null) {
Font font= getDialogArea().getFont();
FontData[] data= font.getFontData();
for (int i= 0; i < data.length; i++) {
data[i].setStyle(SWT.BOLD);
}
fBoldFont= new Font(font.getDevice(), data);
}
return fBoldFont;
}
}
public class CDINamedBeanLabelProvider implements IStyledLabelProvider, ILabelProvider {
final Color gray = new Color(null, 128, 128, 128);
Styler nameStyle;
final Styler beanPathStyle = new CDIBeanStyler(gray);
private Styler getNameStyle() {
if(nameStyle==null) {
nameStyle = new CDIBeanStyler(true);
}
return nameStyle;
}
@Override
public Image getImage(Object element) {
if (element instanceof CDINamedBeanWrapper) {
return CDIImages.getImageByElement(((CDINamedBeanWrapper)element).getBean());
}
return null;
}
public String getTextString(Object element) {
StringBuffer text = new StringBuffer();
if (element instanceof CDINamedBeanWrapper) {
CDINamedBeanWrapper beanWrapper = (CDINamedBeanWrapper) element;
//1. bean name
text.append(beanWrapper.getBeanName());
//2. bean location
IBean b = beanWrapper.getBean();
if (b != null) {
String beanLocation = BeanPresentationUtil.getBeanLocation(b, true);
text.append(beanLocation);
}
}
return text.toString();
}
@Override
public String getText(Object element) {
return getStyledText(element).getString();
}
@Override
public StyledString getStyledText(Object element) {
StyledString styledString = new StyledString();
if (element instanceof CDINamedBeanWrapper) {
CDINamedBeanWrapper beanWrapper = (CDINamedBeanWrapper) element;
//1. bean name
styledString.append(beanWrapper.getBeanName(), getNameStyle());
//2. bean location
IBean b = beanWrapper.getBean();
if (b != null) {
String beanLocation = BeanPresentationUtil.getBeanLocation(b, true);
styledString.append(beanLocation, beanPathStyle);
}
}
return styledString;
}
@Override
public void addListener(ILabelProviderListener listener) {
}
@Override
public void dispose() {
}
@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}
@Override
public void removeListener(ILabelProviderListener listener) {
}
}
public class CDINamedBeanWrapper {
private String beanName;
private String projectName;
private IBean bean;
public CDINamedBeanWrapper(String beanName, String projectName) {
this.beanName = beanName;
this.projectName = projectName;
}
public CDINamedBeanWrapper(String beanName, String projectName,
IBean bean) {
this(beanName, projectName);
this.bean = bean;
}
public String getBeanName() {
return beanName;
}
public String getProjectName() {
return projectName;
}
public IBean getBean() {
if (bean == null) {
IProject project = ResourcesPlugin.getWorkspace().getRoot()
.getProject(projectName);
if (project.isAccessible()) {
ICDIProject cdiProject = CDICorePlugin.getCDIProject(
project, true);
if (cdiProject != null) {
Collection<IBean> beans = cdiProject
.getBeans(beanName, true);
if (!beans.isEmpty())
return beans.iterator().next();
}
}
return null;
}
return bean;
}
public boolean equals(Object obj) {
if(!(obj instanceof CDINamedBeanWrapper)) {
return false;
}
String s1 = new CDINamedBeanLabelProvider().getTextString(this);
String s2 = new CDINamedBeanLabelProvider().getTextString(obj);
return s1.equals(s2);
}
public int hashCode() {
return new CDINamedBeanLabelProvider().getTextString(this).hashCode();
}
}
public static void validateHistory(ICDIProject cdiProject) {
XMLMemento memento = loadMemento();
if (memento != null) {
validateHistory(cdiProject, memento);
saveMemento(memento);
}
}
public static void validateHistory(ICDIProject cdiProject, XMLMemento memento) {
String cdiProjectName = cdiProject.getNature().getProject().getName();
XMLMemento historyMemento = (XMLMemento) memento
.getChild(ROOT_NODE);
if (historyMemento == null) {
return;
}
IMemento[] mementoElements = historyMemento.getChildren(INFO_NODE);
for (int i = 0; i < mementoElements.length; ++i) {
IMemento mem = mementoElements[i];
String projectName = mem.getString(PROJECT_NAME);
if (projectName == null) {
mem.putString(DELETED, YES);
continue;
}
if (projectName.equals(cdiProjectName)) {
if (!cdiProject.getNature().getProject().exists()) {
mem.putString(DELETED, YES);
continue;
}
String beanName = mem.getString(BEAN_NAME);
if (beanName == null) {
mem.putString(DELETED, YES);
continue;
}
Collection<IBean> beans = cdiProject
.getBeans(beanName, true);
IBean bean = (beans == null || beans.isEmpty() ? null : beans.iterator().next());
if (bean == null)
mem.putString(DELETED, YES);
else
mem.putString(DELETED, NO);
}
}
}
}