/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 * 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Stephan Herrmann - Contribution for Bug 465293 - External annotation path per container and project
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.wizards.buildpaths;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;

import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ResourceTransfer;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;

import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.launching.AbstractVMInstall;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;

import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess;

import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.actions.JarImportWizardAction;
import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
import org.eclipse.jdt.internal.ui.jarimport.JarImportWizard;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.RootCPListElement.RootNodeChange;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField;


public class LibrariesWorkbookPage extends BuildPathBasePage {

	private final ListDialogField<CPListElement> fClassPathList;
	private IJavaProject fCurrJProject;

	private final TreeListDialogField<CPListElement> fLibrariesList;

	private Control fSWTControl;
	private final IWorkbenchPreferenceContainer fPageContainer;

	private final int IDX_ADDJAR= 0;
	private final int IDX_ADDEXT= 1;
	private final int IDX_ADDVAR= 2;
	private final int IDX_ADDLIB= 3;
	private final int IDX_ADDFOL= 4;
	private final int IDX_ADDEXTFOL= 5;

	private final int IDX_EDIT= 7;
	private final int IDX_REMOVE= 8;

	private final int IDX_REPLACE= 10;

	private boolean dragDropEnabled;
	private Object draggedItemsLibrary;
	private boolean fromModularLibrary;
	
	public LibrariesWorkbookPage(CheckedListDialogField<CPListElement> classPathList, IWorkbenchPreferenceContainer pageContainer) {
		fClassPathList= classPathList;
		fPageContainer= pageContainer;
		fSWTControl= null;

		String[] buttonLabels= new String[] {
			NewWizardMessages.LibrariesWorkbookPage_libraries_addjar_button,
			NewWizardMessages.LibrariesWorkbookPage_libraries_addextjar_button,
			NewWizardMessages.LibrariesWorkbookPage_libraries_addvariable_button,
			NewWizardMessages.LibrariesWorkbookPage_libraries_addlibrary_button,
			NewWizardMessages.LibrariesWorkbookPage_libraries_addclassfolder_button,
			NewWizardMessages.LibrariesWorkbookPage_libraries_addextfolder_button,
			/* */ null,
			NewWizardMessages.LibrariesWorkbookPage_libraries_edit_button,
			NewWizardMessages.LibrariesWorkbookPage_libraries_remove_button,
			/* */ null,
			NewWizardMessages.LibrariesWorkbookPage_libraries_replace_button
		};

		LibrariesAdapter adapter= new LibrariesAdapter();

		fLibrariesList= new TreeListDialogField<>(adapter, buttonLabels, new CPListLabelProvider());
		fLibrariesList.setDialogFieldListener(adapter);
		fLibrariesList.setLabelText(NewWizardMessages.LibrariesWorkbookPage_libraries_label);

		fLibrariesList.enableButton(IDX_REMOVE, false);
		fLibrariesList.enableButton(IDX_EDIT, false);
		fLibrariesList.enableButton(IDX_REPLACE, false);

		fLibrariesList.setViewerComparator(new CPListElementSorter());

	}

	@Override
	public void init(IJavaProject jproject) {
		fCurrJProject= jproject;
		if (Display.getCurrent() != null) {
			updateLibrariesList();
		} else {
			Display.getDefault().asyncExec(new Runnable() {
				@Override
				public void run() {
					updateLibrariesList();
				}
			});
		}
	}

	private void updateLibrariesList() {
		if(JavaModelUtil.is9OrHigher(fCurrJProject)) {
			updateLibrariesListWithRootNode();
			return;
		}
		List<CPListElement> cpelements= fClassPathList.getElements();
		List<CPListElement> libelements= new ArrayList<>(cpelements.size());

		int nElements= cpelements.size();
		for (int i= 0; i < nElements; i++) {
			CPListElement cpe= cpelements.get(i);
			if (isEntryKind(cpe.getEntryKind())) {
				libelements.add(cpe);
			}
		}
		fLibrariesList.setElements(libelements);
	}
	private void updateLibrariesListWithRootNode() {
		RootCPListElement rootClasspath= new RootCPListElement(fCurrJProject, NewWizardMessages.PathRootWorkbookPage_classpath,false);
		RootCPListElement rootModulepath= new RootCPListElement(fCurrJProject,NewWizardMessages.PathRootWorkbookPage_modulepath,true);

		List<CPListElement> cpelements= fClassPathList.getElements();
		List<CPListElement> libelements= new ArrayList<>(cpelements.size());

		int nElements= cpelements.size();
		int size= fLibrariesList.getElements().size();
		for (int i= 0; i < nElements; i++) {
			CPListElement cpe= cpelements.get(i);
			if (isEntryKind(cpe.getEntryKind())) {
				if (size > 0) {
					// only for update
					cpe= checkAndUpdateIfModularJRE(cpe);
				}
				if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
					if (cpe.getAttribute(CPListElement.MODULE) == null && !isJREContainer(cpe.getPath())) {
						cpe.updateExtraAttributeOfClasspathEntry();
						cpe.setAttribute(CPListElement.MODULE, null);
					}
				}
				Object mod= cpe.getAttribute(CPListElement.MODULE);
				if(mod == null) {
					rootClasspath.addCPListElement(cpe);
				} else {
					rootModulepath.addCPListElement(cpe);
				}
					
			}
		}
		libelements.add(rootModulepath);
		libelements.add(rootClasspath);
		fLibrariesList.setTreeExpansionLevel(2);
		fLibrariesList.setElements(libelements);
		
		fLibrariesList.enableButton(IDX_ADDEXT, false);
		fLibrariesList.enableButton(IDX_ADDFOL, false);
		fLibrariesList.enableButton(IDX_ADDEXTFOL, false);
		fLibrariesList.enableButton(IDX_ADDJAR, false);
		fLibrariesList.enableButton(IDX_ADDLIB, false);
		fLibrariesList.enableButton(IDX_ADDVAR, false);
		
		if (!dragDropEnabled) {
			enableDragDropSupport();
		}
		
	}
	
	private CPListElement checkAndUpdateIfModularJRE(CPListElement cpe) {
		boolean modularJava= false;
		IVMInstall vmInstall= JavaRuntime.getVMInstall(cpe.getPath());
		if (vmInstall != null) {
			modularJava= JavaRuntime.isModularJava(vmInstall);
		}
		if (modularJava) {
			// If JRE is updated to modular JRE, then cpe element has to be recreated
			// so as to have the modular structure 
			cpe= CPListElement.create(cpe.getClasspathEntry(), true, fCurrJProject);
		}
		return cpe;
	}

	private void enableDragDropSupport() {
		dragDropEnabled= true;
		int ops= DND.DROP_MOVE;
		Transfer[] transfers= new Transfer[] { ResourceTransfer.getInstance(), FileTransfer.getInstance() };
		fLibrariesList.getTreeViewer().addDragSupport(ops, transfers, new DragSourceListener() {
			@Override
			public void dragStart(DragSourceEvent event) {
				IStructuredSelection ssel= (IStructuredSelection) fLibrariesList.getTreeViewer().getSelection();
				if (ssel == null || ssel.isEmpty()) {
					event.doit= false;
				}
				if (ssel != null) {
					Object[] ele= ssel.toArray();
					for (Object element : ele) {
						// dont start drag on root nodes
						if (element instanceof RootCPListElement) {
							event.doit= false;
							break;
						}
						if (element instanceof CPListElement) {
							CPListElement cpe= (CPListElement) element;
							List<CPListElement> elements= fLibrariesList.getElements();
							for (Object cpListElement : elements) {
								if (cpListElement instanceof RootCPListElement) {
									RootCPListElement root= (RootCPListElement) cpListElement;
									if (root.getChildren().contains(cpe)) {
										fromModularLibrary= root.isModulePathRootNode();
										break;
									}
								}
							}
							if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
								IPath path= cpe.getPath();
								if (path != null) {
									IVMInstall vmInstall= JavaRuntime.getVMInstall(path);
									if (vmInstall != null) {
										boolean isJRE= isJREContainer(path);
										if (isJRE == true) {
											event.doit= false;
											break;
										}
									}
								}
							}
						}
					}
				}
			}

			@Override
			public void dragSetData(DragSourceEvent event) {
				IStructuredSelection ssel= (IStructuredSelection) fLibrariesList.getTreeViewer().getSelection();
				event.data= ssel.toArray();
				draggedItemsLibrary= ssel.toArray();
			}

			@Override
			public void dragFinished(DragSourceEvent event) {
				draggedItemsLibrary= null;
			}
		});

		fLibrariesList.getTreeViewer().addDropSupport(ops, transfers, new ViewerDropAdapter(fLibrariesList.getTreeViewer()) {
			@Override
			public boolean performDrop(Object data) {
				Object[] objects= (data == null) ? (Object[]) draggedItemsLibrary : (Object[]) data;
				if (objects == null)
					return false;
				Object target= getCurrentTarget();
				if (target instanceof RootCPListElement) {
					for (Object object : objects) {
						if (!(object instanceof CPListElement))
							return false;
						if(object instanceof RootCPListElement)
							return false;
						boolean contains= ((RootCPListElement) target).getChildren().contains(object);
						if (contains == true)
							return false;
						RootCPListElement rootNode= (RootCPListElement) target;
						boolean isModular= rootNode.isModulePathRootNode();
						RootNodeChange direction= RootNodeChange.fromOldAndNew(!isModular, isModular);
						if (direction != RootNodeChange.NoChange) {
							// pre-process container items while moving to modulepath
							CPListElement cpe= (CPListElement) object;
							if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER && isModular) {
								IClasspathEntry entry= cpe.getClasspathEntry();
								IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
								boolean hasModAttr= false;
								for (IClasspathAttribute attr : extraAttributes) {
									if (IClasspathAttribute.MODULE.equals(attr.getName())) {
										hasModAttr= true;
										break;
									}
								}
								if (!hasModAttr) {
									cpe.updateExtraAttributeOfClasspathEntry();
								}
							}

							moveCPElementAcrossNode(fLibrariesList, (CPListElement) object, direction);
						}
						((CPListElement) object).setAttribute(IClasspathAttribute.MODULE, isModular ? new ModuleEncapsulationDetail[0] : null);
					}
					return true;

				}
				return false;
			}

			@Override
			public boolean validateDrop(Object target, int operation, TransferData transferType) {
				if (!(target instanceof RootCPListElement))
					return false;
				RootCPListElement root= (RootCPListElement) target;
				return fromModularLibrary ? root.isClassPathRootNode() : root.isModulePathRootNode();
			}

		});


	}

	private boolean isJREContainer(IPath path) {
		if (path == null)
			return false;
		String[] segments= path.segments();
		for (String seg : segments) {
			if (seg.equals(JavaRuntime.JRE_CONTAINER)) {
				return true;
			}
		}
		return false;
	}
	
	boolean hasRootNodes(){
		if (fLibrariesList == null)
			return false;
		if(fLibrariesList.getSize()==0)
			return false;
		if(fLibrariesList.getElement(0).isRootNodeForPath())
			return true;
		return false;
	}

	// -------- UI creation

	@Override
	public Control getControl(Composite parent) {
		PixelConverter converter= new PixelConverter(parent);

		Composite composite= new Composite(parent, SWT.NONE);

		LayoutUtil.doDefaultLayout(composite, new DialogField[] { fLibrariesList }, true, SWT.DEFAULT, SWT.DEFAULT);
		LayoutUtil.setHorizontalGrabbing(fLibrariesList.getTreeControl(null));

		int buttonBarWidth= converter.convertWidthInCharsToPixels(24);
		fLibrariesList.setButtonsMinWidth(buttonBarWidth);

		fLibrariesList.setViewerComparator(new CPListElementSorter());

		fSWTControl= composite;

		return composite;
	}

	private Shell getShell() {
		if (fSWTControl != null) {
			return fSWTControl.getShell();
		}
		return JavaPlugin.getActiveWorkbenchShell();
	}


	private class LibrariesAdapter extends CPListAdapter {

		// -------- IListAdapter --------
		@Override
		public void customButtonPressed(TreeListDialogField<CPListElement> field, int index) {
			libaryPageCustomButtonPressed(field, index);
		}

		@Override
		public void selectionChanged(TreeListDialogField<CPListElement> field) {
			libaryPageSelectionChanged(field);
		}

		@Override
		public void doubleClicked(TreeListDialogField<CPListElement> field) {
			libaryPageDoubleClicked(field);
		}

		@Override
		public void keyPressed(TreeListDialogField<CPListElement> field, KeyEvent event) {
			libaryPageKeyPressed(field, event);
		}

		@Override
		public Object[] getChildren(TreeListDialogField<CPListElement> field, Object element) {
			if (element instanceof CPListElementAttribute) {
				CPListElementAttribute attribute= (CPListElementAttribute) element;
				if (CPListElement.ACCESSRULES.equals(attribute.getKey())) {
					return (IAccessRule[]) attribute.getValue();
				}
			}
			return super.getChildren(field, element);
		}

		// ---------- IDialogFieldListener --------

		@Override
		public void dialogFieldChanged(DialogField field) {
			libaryPageDialogFieldChanged(field);
		}
	}

	/**
	 * A button has been pressed.
	 *
	 * @param field the dialog field containing the button
	 * @param index the index of the button
	 */
	private void libaryPageCustomButtonPressed(DialogField field, int index) {
		CPListElement[] libentries= null;
		switch (index) {
		case IDX_ADDJAR: /* add jar */
			libentries= openJarFileDialog(null);
			break;
		case IDX_ADDEXT: /* add external jar */
			libentries= openExtJarFileDialog(null);
			break;
		case IDX_ADDVAR: /* add variable */
			libentries= openVariableSelectionDialog(null);
			break;
		case IDX_ADDLIB: /* add library */
			libentries= openContainerSelectionDialog(null);
			break;
		case IDX_ADDFOL: /* add folder */
			libentries= openClassFolderDialog(null);
			break;
		case IDX_ADDEXTFOL: /* add external folder */
			libentries= openExternalClassFolderDialog(null);
			break;
		case IDX_EDIT: /* edit */
			editEntry();
			return;
		case IDX_REMOVE: /* remove */
			removeEntry();
			return;
		case IDX_REPLACE: /* replace */
			replaceJarFile();
			return;
		}
		if (libentries != null) {
			int nElementsChosen= libentries.length;
			// remove duplicates
			List<CPListElement> cplist= fLibrariesList.getElements();
			List<CPListElement> elementsToAdd= new ArrayList<>(nElementsChosen);

			for (int i= 0; i < nElementsChosen; i++) {
				CPListElement curr= libentries[i];
				boolean contains= cplist.contains(curr);
				if(hasRootNodes()) {
					contains= hasCurrentElement(cplist,curr);
				}
				if (!contains && !elementsToAdd.contains(curr)) {
					elementsToAdd.add(curr);
					curr.setAttribute(CPListElement.SOURCEATTACHMENT, BuildPathSupport.guessSourceAttachment(curr));
					curr.setAttribute(CPListElement.JAVADOC, BuildPathSupport.guessJavadocLocation(curr));
				}
			}
			if (!elementsToAdd.isEmpty() && (index == IDX_ADDFOL)) {
				askForAddingExclusionPatternsDialog(elementsToAdd);
			}
			
			if(!hasRootNodes()) {
				fLibrariesList.addElements(elementsToAdd);
			} else {
				// on root nodes, only additions allowed, rest disabled
				List<Object> selectedElements= fLibrariesList.getSelectedElements();
				List<CPListElement> elements= fLibrariesList.getElements();
				// sanity check, button should only be enabled if exactly one root node is selected 
				if(selectedElements.size() != 1) {
					return;
				}
				fLibrariesList.removeAllElements();
				RootCPListElement selectedCPElement= (RootCPListElement) selectedElements.get(0);
				if(selectedCPElement.isClassPathRootNode()) {
					for (CPListElement cpListElement : elementsToAdd) {
						cpListElement.setAttribute(IClasspathAttribute.MODULE, null);
					}
				} else if(selectedCPElement.isModulePathRootNode()) {
					for (CPListElement cpListElement : elementsToAdd) {
						Object attribute= cpListElement.getAttribute(IClasspathAttribute.MODULE);
						if(attribute == null) {
							cpListElement.setAttribute(IClasspathAttribute.MODULE, new ModuleEncapsulationDetail[0]);
						}
					}
				}
				selectedCPElement.addCPListElement(elementsToAdd);					
				
				fLibrariesList.setElements(elements);
				fLibrariesList.refresh();
				fLibrariesList.getTreeViewer().expandToLevel(2);		
			}	
			
			if (index == IDX_ADDLIB || index == IDX_ADDVAR) {
				fLibrariesList.refresh();
			}
			fLibrariesList.postSetSelection(new StructuredSelection(libentries));
		}
	}

	private boolean hasCurrentElement(List<CPListElement> cplist, CPListElement curr) {
		//note that the same cpelement with different attribute can be added
		for (CPListElement cpListElement : cplist) {
			if(cpListElement.isRootNodeForPath()) {
				boolean cont= ( (RootCPListElement)cpListElement).getChildren().contains(curr);
				if(cont == true) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public void addElement(CPListElement element) {
		fLibrariesList.addElement(element);
		fLibrariesList.postSetSelection(new StructuredSelection(element));
	}

	private void askForAddingExclusionPatternsDialog(List<CPListElement> newEntries) {
		HashSet<CPListElement> modified= new HashSet<>();
		List<CPListElement> existing= fClassPathList.getElements();
		fixNestingConflicts(newEntries.toArray(new CPListElement[newEntries.size()]), existing.toArray(new CPListElement[existing.size()]), modified);
		if (!modified.isEmpty()) {
			String title= NewWizardMessages.LibrariesWorkbookPage_exclusion_added_title;
			String message= NewWizardMessages.LibrariesWorkbookPage_exclusion_added_message;
			MessageDialog.openInformation(getShell(), title, message);
		}
	}

	protected void libaryPageDoubleClicked(TreeListDialogField<CPListElement> field) {
		List<?> selection= field.getSelectedElements();
		if (canEdit(selection)) {
			editEntry();
		}
	}

	protected void libaryPageKeyPressed(TreeListDialogField<CPListElement> field, KeyEvent event) {
		if (field == fLibrariesList) {
			if (event.character == SWT.DEL && event.stateMask == 0) {
				List<?> selection= field.getSelectedElements();
				if (canRemove(selection)) {
					removeEntry();
				}
			}
		}
	}

	private void replaceJarFile() {
		final IPackageFragmentRoot root= getSelectedPackageFragmentRoot();
		if (root != null) {
			final IImportWizard wizard= new JarImportWizard(false);
			wizard.init(PlatformUI.getWorkbench(), new StructuredSelection(root));
			final WizardDialog dialog= new WizardDialog(getShell(), wizard);
			dialog.create();
			dialog.getShell().setSize(Math.max(JarImportWizardAction.SIZING_WIZARD_WIDTH, dialog.getShell().getSize().x), JarImportWizardAction.SIZING_WIZARD_HEIGHT);
			PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IJavaHelpContextIds.JARIMPORT_WIZARD_PAGE);
			dialog.open();
		}
	}

	private IPackageFragmentRoot getSelectedPackageFragmentRoot() {
		final List<Object> elements= fLibrariesList.getSelectedElements();
		if (elements.size() == 1) {
			final Object object= elements.get(0);
			if (object instanceof CPListElement) {
				final CPListElement element= (CPListElement) object;
				final IClasspathEntry entry= element.getClasspathEntry();
				if (JarImportWizard.isValidClassPathEntry(entry)) {
					final IJavaProject project= element.getJavaProject();
					if (project != null) {
						try {
							final IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
							for (int index= 0; index < roots.length; index++) {
								if (entry.equals(roots[index].getRawClasspathEntry()))
									return roots[index];
							}
						} catch (JavaModelException exception) {
							JavaPlugin.log(exception);
						}
					}
				}
			}
		}
		return null;
	}

	private void removeEntry() {
		List<Object> selElements= fLibrariesList.getSelectedElements();
		HashMap<CPListElement, HashSet<String>> containerEntriesToUpdate= new HashMap<>();
		for (int i= selElements.size() - 1; i >= 0 ; i--) {
			Object elem= selElements.get(i);
			if (elem instanceof CPListElementAttribute) {
				CPListElementAttribute attrib= (CPListElementAttribute) elem;
				String key= attrib.getKey();
				if (attrib.isBuiltIn()) {
					Object value= null;
					if (key.equals(CPListElement.ACCESSRULES)) {
						value= new IAccessRule[0];
					}
					attrib.setValue(value);
				} else {
					removeCustomAttribute(attrib);
				}
				selElements.remove(i);
				if (attrib.getParent().getParentContainer() instanceof CPListElement) { // inside a container: apply changes right away
					CPListElement containerEntry= attrib.getParent();
					HashSet<String> changedAttributes= containerEntriesToUpdate.get(containerEntry);
					if (changedAttributes == null) {
						changedAttributes= new HashSet<>();
						containerEntriesToUpdate.put(containerEntry, changedAttributes);
					}
					changedAttributes.add(key); // collect the changed attributes
				}
			} else if (elem instanceof ModuleEncapsulationDetail) {
				removeEncapsulationDetail((ModuleEncapsulationDetail) elem);
			}
		}
		if (selElements.isEmpty()) {
			fLibrariesList.refresh();
			fClassPathList.dialogFieldChanged(); // validate
		} else {
			if(hasRootNodes()) {
				List<CPListElement> elements= fLibrariesList.getElements();
				for (CPListElement cpListElement : elements) {
					((RootCPListElement)cpListElement).getChildren().removeAll(selElements);
				}
				fLibrariesList.getTreeViewer().remove(selElements.toArray());
				fLibrariesList.dialogFieldChanged();
				
			}
			else {
				fLibrariesList.removeElements(selElements);
			}
		
		}
		for (Iterator<Map.Entry<CPListElement, HashSet<String>>> iter= containerEntriesToUpdate.entrySet().iterator(); iter.hasNext();) {
			Map.Entry<CPListElement, HashSet<String>> entry= iter.next();
			CPListElement curr= entry.getKey();
			HashSet<String> attribs= entry.getValue();
			String[] changedAttributes= attribs.toArray(new String[attribs.size()]);
			IClasspathEntry changedEntry= curr.getClasspathEntry();
			updateContainerEntry(changedEntry, changedAttributes, fCurrJProject, ((CPListElement) curr.getParentContainer()).getPath());
		}
	}

	private boolean canRemove(List<?> selElements) {
		if (selElements.size() == 0) {
			return false;
		}
		for (int i= 0; i < selElements.size(); i++) {
			Object elem= selElements.get(i);
			if (elem instanceof CPListElementAttribute) {
				CPListElementAttribute attrib= (CPListElementAttribute) elem;
				
				if (IClasspathAttribute.MODULE.equals(attrib.getKey())) {
					return false;
				}
						
				if (attrib.isNonModifiable()) {
					return false;
				}
				if (attrib.isBuiltIn()) {
					if (attrib.getParent().isInContainer(JavaRuntime.JRE_CONTAINER) && CPListElement.ACCESSRULES.equals(attrib.getKey())) {
						return false; // workaround for 166519 until we have full story
					}
					if (attrib.getKey().equals(CPListElement.ACCESSRULES)) {
						return ((IAccessRule[]) attrib.getValue()).length > 0;
					}
					if (attrib.getValue() == null) {
						return false;
					}
				} else {
					if (!canRemoveCustomAttribute(attrib)) {
						return false;
					}
				}
			} else if (elem instanceof CPListElement) {
				CPListElement curr= (CPListElement) elem;
				if(curr.isRootNodeForPath()) {
					return false;
				}
				if (curr.getParentContainer() != null) {
					return false;
				}
			} else if (elem instanceof ModuleEncapsulationDetail) {
				return true;
			} else { // unknown element
				return false;
			}
		}
		return true;
	}

	/**
	 * Method editEntry.
	 */
	private void editEntry() {
		List<?> selElements= fLibrariesList.getSelectedElements();
		if (selElements.size() != 1) {
			return;
		}
		Object elem= selElements.get(0);
		
		boolean canEdit= false;
		if(hasRootNodes()) {
			canEdit= ((RootCPListElement)fLibrariesList.getElement(0)).getChildren().indexOf(elem) != -1 || 
					((RootCPListElement)fLibrariesList.getElement(1)).getChildren().indexOf(elem) != -1 ;
			
		}
		if (canEdit || fLibrariesList.getIndexOfElement(elem) != -1 ) {
			editElementEntry((CPListElement) elem);
		} else if (elem instanceof CPListElementAttribute) {
			editAttributeEntry((CPListElementAttribute) elem);
		}
	}

	private void editAttributeEntry(CPListElementAttribute elem) {
		String key= elem.getKey();
		CPListElement selElement= elem.getParent();

		CPListElementAttribute[] allAttributes= selElement.getAllAttributes();
		boolean canEditEncoding= false;
		for (int i= 0; i < allAttributes.length; i++) {
			if (CPListElement.SOURCE_ATTACHMENT_ENCODING.equals(allAttributes[i].getKey())) {
				canEditEncoding= !(allAttributes[i].isNonModifiable() || allAttributes[i].isNotSupported());
			}
		}
		if (key.equals(CPListElement.SOURCEATTACHMENT)) {
			IClasspathEntry result= BuildPathDialogAccess.configureSourceAttachment(getShell(), selElement.getClasspathEntry(), canEditEncoding);
			if (result != null) {
				selElement.setAttribute(CPListElement.SOURCEATTACHMENT, result.getSourceAttachmentPath());
				selElement.setAttribute(CPListElement.SOURCE_ATTACHMENT_ENCODING, SourceAttachmentBlock.getSourceAttachmentEncoding(result));
				String[] changedAttributes= { CPListElement.SOURCEATTACHMENT, CPListElement.SOURCE_ATTACHMENT_ENCODING };
				attributeUpdated(selElement, changedAttributes);
				fLibrariesList.refresh(elem);
				fLibrariesList.update(selElement); // image
				fClassPathList.refresh(); // images
				updateEnabledState();
			}
		} else if (key.equals(CPListElement.ACCESSRULES)) {
			AccessRulesDialog dialog= new AccessRulesDialog(getShell(), selElement, fCurrJProject, fPageContainer != null);
			int res= dialog.open();
			if (res == Window.OK || res == AccessRulesDialog.SWITCH_PAGE) {
				selElement.setAttribute(CPListElement.ACCESSRULES, dialog.getAccessRules());
				String[] changedAttributes= { CPListElement.ACCESSRULES };
				attributeUpdated(selElement, changedAttributes);

				fLibrariesList.refresh(elem);
				fClassPathList.dialogFieldChanged(); // validate
				updateEnabledState();

				if (res == AccessRulesDialog.SWITCH_PAGE) { // switch after updates and validation
					dialog.performPageSwitch(fPageContainer);
				}
			}
		} else if (key.equals(CPListElement.MODULE)) {
			boolean wasModular= selElement.getAttribute(CPListElement.MODULE) != null;
			if (showModuleDialog(getShell(), elem)) {
				String[] changedAttributes= { CPListElement.MODULE };
				attributeUpdated(selElement, changedAttributes);
				if (hasRootNodes()) {
					boolean isModular= selElement.getAttribute(CPListElement.MODULE) != null;
					RootNodeChange direction= RootNodeChange.fromOldAndNew(wasModular, isModular);
					if (direction != RootNodeChange.NoChange) {
						moveCPElementAcrossNode(fLibrariesList, selElement, direction);
					}
				}
				fLibrariesList.refresh(elem);
				fClassPathList.dialogFieldChanged(); // validate
				updateEnabledState();
			}
		} else {
			if (editCustomAttribute(getShell(), elem)) {
				String[] changedAttributes= { key };
				attributeUpdated(selElement, changedAttributes);
				if(key.equals(CPListElement.TEST) || key.equals(CPListElement.WITHOUT_TEST_CODE)) {
					fLibrariesList.refresh(elem.getParent());
				} else { 
					fLibrariesList.refresh(elem);
				}
				fClassPathList.dialogFieldChanged(); // validate
				updateEnabledState();
				if (key.equals(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH)) {
					if (fCurrJProject.getOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, true).equals(JavaCore.DISABLED)) {
						MessageDialog messageDialog= new MessageDialog(getShell(),
								NewWizardMessages.LibrariesWorkbookPage_externalAnnotationNeedsNullAnnotationEnabled_title,
								null,
								NewWizardMessages.LibrariesWorkbookPage_externalAnnotationNeedsNullAnnotationEnabled_message,
								MessageDialog.INFORMATION, new String[] { IDialogConstants.OK_LABEL },
								0);
						messageDialog.open();
					}
				}
			}
		}
	}

	private void attributeUpdated(CPListElement selElement, String[] changedAttributes) {
		Object parentContainer= selElement.getParentContainer();
		if (parentContainer instanceof CPListElement) { // inside a container: apply changes right away
			IClasspathEntry updatedEntry= selElement.getClasspathEntry();
			updateContainerEntry(updatedEntry, changedAttributes, fCurrJProject, ((CPListElement) parentContainer).getPath());
		}
	}

	private void updateContainerEntry(final IClasspathEntry newEntry, final String[] changedAttributes, final IJavaProject jproject, final IPath containerPath) {
		try {
			IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
				@Override
				public void run(IProgressMonitor monitor) throws CoreException {
					BuildPathSupport.modifyClasspathEntry(null, newEntry, changedAttributes, jproject, containerPath, false, monitor);
				}
			};
			PlatformUI.getWorkbench().getProgressService().run(true, true, new WorkbenchRunnableAdapter(runnable));

		} catch (InvocationTargetException e) {
			String title= NewWizardMessages.LibrariesWorkbookPage_configurecontainer_error_title;
			String message= NewWizardMessages.LibrariesWorkbookPage_configurecontainer_error_message;
			ExceptionHandler.handle(e, getShell(), title, message);
		} catch (InterruptedException e) {
			//
		}
	}

	private void editElementEntry(CPListElement elem) {
		CPListElement[] res= null;

		switch (elem.getEntryKind()) {
		case IClasspathEntry.CPE_CONTAINER:
			res= openContainerSelectionDialog(elem);
			break;
		case IClasspathEntry.CPE_LIBRARY:
			IResource resource= elem.getResource();
			if (resource == null) {
				File file= elem.getPath().toFile();
				if (file.isDirectory()) {
					res= openExternalClassFolderDialog(elem);
				} else {
					res= openExtJarFileDialog(elem);
				}
			} else if (resource.getType() == IResource.FOLDER) {
				if (resource.exists()) {
					res= openClassFolderDialog(elem);
				} else {
					res= openNewClassFolderDialog(elem);
				}
			} else if (resource.getType() == IResource.FILE) {
				res= openJarFileDialog(elem);
			}
			break;
		case IClasspathEntry.CPE_VARIABLE:
			res= openVariableSelectionDialog(elem);
			break;
		}
		if (res != null && res.length > 0) {
			CPListElement curr= res[0];
			Object attrib= curr.getAttribute(CPListElement.MODULE);
			curr.setExported(elem.isExported());
			curr.setAttributesFromExisting(elem);
			// the module attribute may be changed in curr with respect to elem
			if (attrib != null) {
				curr.setAttribute(IClasspathAttribute.MODULE, attrib);
			}
			if (hasRootNodes()) {
				for (int i= 0; i < fLibrariesList.getElements().size(); i++) {
					CPListElement cpe= fLibrariesList.getElement(i);
					if (cpe.isRootNodeForPath()) {
						if ((((RootCPListElement)cpe).getChildren().contains(elem))) {
							for (int j= 0; j < ((RootCPListElement)cpe).getChildren().size(); j++) {
								// find index
								Object obj= ((RootCPListElement) cpe).getChildren().get(j);
								if (obj.equals(elem)) {
									((RootCPListElement) cpe).getChildren().set(j, curr);
									RootNodeChange changeNodeDirection= doesElementNeedNodeChange(elem, curr);
									if (changeNodeDirection != RootNodeChange.NoChange) {
										moveCPElementAcrossNode(fLibrariesList, curr, changeNodeDirection);
										CPListElementAttribute moduleAttr= curr.findAttributeElement(CPListElement.MODULE);
										Object value=  (changeNodeDirection == RootNodeChange.ToModulepath) ? new ModuleEncapsulationDetail[0] : null;
										if (moduleAttr != null) {
											moduleAttr.setValue(value);
										} else {
											curr.setAttribute(CPListElement.MODULE, value);
										}
									}
									fLibrariesList.dialogFieldChanged();
									fLibrariesList.refresh();
									break;
								}
							}
						}
					}
				}
			} else {
				fLibrariesList.replaceElement(elem, curr);
			}
			if (elem.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
				fLibrariesList.refresh();
			}
		}

	}

	/**
	 * @param elem is former cpelement
	 * @param curr is new cpelement
	 * @return 0 is no change is required, -1 if modular element is removed, +1 if non-modular element
	 *         is removed.
	 */
	private RootNodeChange doesElementNeedNodeChange(CPListElement elem, CPListElement curr) {
		if (elem.getClasspathEntry().getEntryKind() != IClasspathEntry.CPE_CONTAINER)
			return RootNodeChange.NoChange;
		if (curr.getClasspathEntry().getEntryKind() != IClasspathEntry.CPE_CONTAINER)
			return RootNodeChange.NoChange;
		String v1= null;
		String v2= null;
		IVMInstall vm1= JavaRuntime.getVMInstall(elem.getPath());
		if (vm1 instanceof AbstractVMInstall) {
			v1= ((AbstractVMInstall) vm1).getJavaVersion();
		}
		IVMInstall vm2= JavaRuntime.getVMInstall(curr.getPath());
		if (vm2 instanceof AbstractVMInstall) {
			v2= ((AbstractVMInstall) vm2).getJavaVersion();
		}
		if (v1 != null && v2 != null) {
			boolean mod1= JavaModelUtil.is9OrHigher(v1);
			boolean mod2= JavaModelUtil.is9OrHigher(v2);
			if (mod1 == true && mod2 == true)
				return RootNodeChange.NoChange;
			if (mod1 == false && mod2 == false)
				return RootNodeChange.NoChange;
			if (mod1 == true && mod2 == false) {
				// removed module
				return RootNodeChange.ToClasspath;
			}
			if (mod1 == false && mod2 == true) {
				//added module
				return RootNodeChange.ToModulepath;
			}
		}
		return RootNodeChange.NoChange;
	}

	/**
	 * @param field  the dilaog field
	 */
	private void libaryPageSelectionChanged(DialogField field) {
		List<Object> selected= fLibrariesList.getSelectedElements();
		String text;
		if (selected.size() == 1
				&& selected.get(0) instanceof CPListElementAttribute) {
			String key= ((CPListElementAttribute) selected.get(0)).getKey();
			if (CPListElement.TEST.equals(key) || CPListElement.WITHOUT_TEST_CODE.equals(key)) {
				text= NewWizardMessages.LibrariesWorkbookPage_libraries_toggle_button;
			} else {
				text= NewWizardMessages.LibrariesWorkbookPage_libraries_edit_button;
			}
		} else {
			text= NewWizardMessages.LibrariesWorkbookPage_libraries_edit_button;
		}
		fLibrariesList.getButton(IDX_EDIT).setText(text);
		updateEnabledState();
	}

	private void updateEnabledState() {
		List<?> selElements= fLibrariesList.getSelectedElements();
		fLibrariesList.enableButton(IDX_EDIT, canEdit(selElements));
		fLibrariesList.enableButton(IDX_REMOVE, canRemove(selElements));
		fLibrariesList.enableButton(IDX_REPLACE, getSelectedPackageFragmentRoot() != null);

		boolean addEnabled= containsOnlyTopLevelEntries(selElements);
	
		fLibrariesList.enableButton(IDX_ADDEXT, addEnabled);
		fLibrariesList.enableButton(IDX_ADDFOL, addEnabled);
		fLibrariesList.enableButton(IDX_ADDEXTFOL, addEnabled);
		fLibrariesList.enableButton(IDX_ADDJAR, addEnabled);
		fLibrariesList.enableButton(IDX_ADDLIB, addEnabled);
		fLibrariesList.enableButton(IDX_ADDVAR, addEnabled);
	}
	@Override
	protected boolean containsOnlyTopLevelEntries(List<?> selElements) {
		if(hasRootNodes()==false) {
			return super.containsOnlyTopLevelEntries(selElements);
		}
		if (selElements.size() == 0 || selElements.size() > 1) {
			return false;
		}
		for (int i= 0; i < selElements.size(); i++) {
			Object elem= selElements.get(i);
			if (elem instanceof CPListElement) {
				if (!((CPListElement) elem).isRootNodeForPath()) {
					return false;
				}
			} else {
				return false;
			}
		}
		return true;
	}

	private boolean canEdit(List<?> selElements) {
		if (selElements.size() != 1) {
			return false;
		}
		Object elem= selElements.get(0);
		if (elem instanceof CPListElement) {
			CPListElement curr= (CPListElement) elem;
			if(((CPListElement) elem).isRootNodeForPath()) {
				return false;
			}
			return !(curr.getResource() instanceof IFolder) && curr.getParentContainer() == null;
		}
		if (elem instanceof CPListElementAttribute) {
			CPListElementAttribute attrib= (CPListElementAttribute) elem;
			if (attrib.isNonModifiable()) {
				return false;
			}
			if (!attrib.isBuiltIn()) {
				return canEditCustomAttribute(attrib);
			}
			if (hasRootNodes() && attrib.getKey().equals(IClasspathAttribute.MODULE)) {
				//module attribute should always be enabled
				return true;
			}
			
			return true;
		}
		return false;
	}

	/**
	 * @param field the dialog field
	 */
	private void libaryPageDialogFieldChanged(DialogField field) {
		if (fCurrJProject != null) {
			// already initialized
			updateClasspathList();
		}
	}

	private void updateClasspathList() {
		 List<CPListElement> projelements= fLibrariesList.getElements();
		 List<CPListElement> flattenedProjElements= new ArrayList<>();
		 for ( int i =0; i < projelements.size(); i++ ) {
		 	CPListElement ele= projelements.get(i);
		 	// if root node, collect the CPList elements
		 	if(ele.isRootNodeForPath()) {
		 		ArrayList<Object> children= ((RootCPListElement)ele).getChildren();
		 		for (Iterator<?> iterator= children.iterator(); iterator.hasNext();) {
		 			Object object=  iterator.next();
		 			if(object instanceof CPListElement) {
		 				flattenedProjElements.add((CPListElement) object);
		 			}
		 		}
		 	}
		 	else {
		 		flattenedProjElements.add(ele);
		 	}
		 }

		List<CPListElement> cpelements= fClassPathList.getElements();
		int nEntries= cpelements.size();
		// backwards, as entries will be deleted
		int lastRemovePos= nEntries;
		for (int i= nEntries - 1; i >= 0; i--) {
			CPListElement cpe= cpelements.get(i);
			int kind= cpe.getEntryKind();
			if (isEntryKind(kind)) {
				if (!flattenedProjElements.remove(cpe)) {
					cpelements.remove(i);
					lastRemovePos= i;
				}
			}
		}

		cpelements.addAll(lastRemovePos, flattenedProjElements);

		if (lastRemovePos != nEntries || !flattenedProjElements.isEmpty()) {
			fClassPathList.setElements(cpelements);
		}
	}


	private CPListElement[] openNewClassFolderDialog(CPListElement existing) {
		String title= (existing == null) ? NewWizardMessages.LibrariesWorkbookPage_NewClassFolderDialog_new_title : NewWizardMessages.LibrariesWorkbookPage_NewClassFolderDialog_edit_title;
		IProject currProject= fCurrJProject.getProject();

		NewContainerDialog dialog= new NewContainerDialog(getShell(), title, currProject, getUsedContainers(existing), existing);
		IPath projpath= currProject.getFullPath();
		dialog.setMessage(Messages.format(NewWizardMessages.LibrariesWorkbookPage_NewClassFolderDialog_description, BasicElementLabels.getPathLabel(projpath, false)));
		if (dialog.open() == Window.OK) {
			IFolder folder= dialog.getFolder();
			return new CPListElement[] { newCPLibraryElement(folder) };
		}
		return null;
	}


	private CPListElement[] openClassFolderDialog(CPListElement existing) {
		if (existing == null) {
			IPath[] selected= BuildPathDialogAccess.chooseClassFolderEntries(getShell(), fCurrJProject.getPath(), getUsedContainers(existing));
			if (selected != null) {
				IWorkspaceRoot root= fCurrJProject.getProject().getWorkspace().getRoot();
				ArrayList<CPListElement> res= new ArrayList<>();
				for (int i= 0; i < selected.length; i++) {
					IPath curr= selected[i];
					IResource resource= root.findMember(curr);
					if (resource instanceof IContainer) {
						CPListElement newCPLibraryElement= newCPLibraryElement(resource);
						newCPLibraryElement.setModuleAttributeIf9OrHigher(fCurrJProject);
						res.add(newCPLibraryElement);
					}
				}
				return res.toArray(new CPListElement[res.size()]);
			}
		} else {
			// disabled
		}
		return null;
	}

	private CPListElement[] openJarFileDialog(CPListElement existing) {
		IWorkspaceRoot root= fCurrJProject.getProject().getWorkspace().getRoot();

		if (existing == null) {
			IPath[] selected= BuildPathDialogAccess.chooseJAREntries(getShell(), fCurrJProject.getPath(), getUsedJARFiles(existing));
			if (selected != null) {
				ArrayList<CPListElement> res= new ArrayList<>();

				for (int i= 0; i < selected.length; i++) {
					IPath curr= selected[i];
					IResource resource= root.findMember(curr);
					if (resource instanceof IFile) {
						CPListElement newCPLibraryElement= newCPLibraryElement(resource);
						newCPLibraryElement.setModuleAttributeIf9OrHigher(fCurrJProject);
						res.add(newCPLibraryElement);
					}
				}
				return res.toArray(new CPListElement[res.size()]);
			}
		} else {
			IPath configured= BuildPathDialogAccess.configureJAREntry(getShell(), existing.getPath(), getUsedJARFiles(existing));
			if (configured != null) {
				IResource resource= root.findMember(configured);
				if (resource instanceof IFile) {
					return new CPListElement[] { newCPLibraryElement(resource) };
				}
			}
		}
		return null;
	}

	private IPath[] getUsedContainers(CPListElement existing) {
		ArrayList<IPath> res= new ArrayList<>();
		if (fCurrJProject.exists()) {
			try {
				IPath outputLocation= fCurrJProject.getOutputLocation();
				if (outputLocation != null && outputLocation.segmentCount() > 1) { // != Project
					res.add(outputLocation);
				}
			} catch (JavaModelException e) {
				// ignore it here, just log
				JavaPlugin.log(e.getStatus());
			}
		}

		List<CPListElement> cplist= fLibrariesList.getElements();
		for (int i= 0; i < cplist.size(); i++) {
			CPListElement elem= cplist.get(i);
			if (elem.getEntryKind() == IClasspathEntry.CPE_LIBRARY && (elem != existing)) {
				IResource resource= elem.getResource();
				if (resource instanceof IContainer) {
					res.add(resource.getFullPath());
				}
			}
		}
		return res.toArray(new IPath[res.size()]);
	}

	private IPath[] getUsedJARFiles(CPListElement existing) {
		List<IPath> res= new ArrayList<>();
		List<CPListElement> cplist= fLibrariesList.getElements();
		for (int i= 0; i < cplist.size(); i++) {
			CPListElement elem= cplist.get(i);
			if (elem.getEntryKind() == IClasspathEntry.CPE_LIBRARY && (elem != existing)) {
				IResource resource= elem.getResource();
				if (resource instanceof IFile) {
					res.add(resource.getFullPath());
				}
			}
		}
		return res.toArray(new IPath[res.size()]);
	}

	private CPListElement newCPLibraryElement(IResource res) {
		return new CPListElement(fCurrJProject, IClasspathEntry.CPE_LIBRARY, res.getFullPath(), res);
	}

	private CPListElement[] openExtJarFileDialog(CPListElement existing) {
		if (existing == null) {
			IPath[] selected= BuildPathDialogAccess.chooseExternalJAREntries(getShell());
			if (selected != null) {
				ArrayList<CPListElement> res= new ArrayList<>();
				for (int i= 0; i < selected.length; i++) {
					CPListElement cpListElement= new CPListElement(fCurrJProject, IClasspathEntry.CPE_LIBRARY, selected[i], null);
					cpListElement.setModuleAttributeIf9OrHigher(fCurrJProject);
					res.add(cpListElement);
				}
				return res.toArray(new CPListElement[res.size()]);
			}
		} else {
			IPath path;
			IPackageFragmentRoot[] roots= existing.getJavaProject().findPackageFragmentRoots(existing.getClasspathEntry());
			if (roots.length == 1)
				path= roots[0].getPath();
			else
				path= existing.getPath();
			IPath configured= BuildPathDialogAccess.configureExternalJAREntry(getShell(), path);
			if (configured != null) {
				return new CPListElement[] { new CPListElement(fCurrJProject, IClasspathEntry.CPE_LIBRARY, configured, null) };
			}
		}
		return null;
	}

	private CPListElement[] openExternalClassFolderDialog(CPListElement existing) {
		if (existing == null) {
			IPath[] selected= BuildPathDialogAccess.chooseExternalClassFolderEntries(getShell());
			if (selected != null) {
				ArrayList<CPListElement> res= new ArrayList<>();
				for (int i= 0; i < selected.length; i++) {
					CPListElement cpListElement= new CPListElement(fCurrJProject, IClasspathEntry.CPE_LIBRARY, selected[i], null);
					cpListElement.setModuleAttributeIf9OrHigher(fCurrJProject);
					res.add(cpListElement);
				}
				return res.toArray(new CPListElement[res.size()]);
			}
		} else {
			IPath configured= BuildPathDialogAccess.configureExternalClassFolderEntries(getShell(), existing.getPath());
			if (configured != null) {
				return new CPListElement[] { new CPListElement(fCurrJProject, IClasspathEntry.CPE_LIBRARY, configured, null) };
			}
		}
		return null;
	}

	private CPListElement[] openVariableSelectionDialog(CPListElement existing) {
		List<CPListElement> existingElements= fLibrariesList.getElements();
		ArrayList<IPath> existingPaths= new ArrayList<>(existingElements.size());
		for (int i= 0; i < existingElements.size(); i++) {
			CPListElement elem= existingElements.get(i);
			if (elem.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
				existingPaths.add(elem.getPath());
			}
		}
		IPath[] existingPathsArray= existingPaths.toArray(new IPath[existingPaths.size()]);

		if (existing == null) {
			IPath[] paths= BuildPathDialogAccess.chooseVariableEntries(getShell(), existingPathsArray);
			if (paths != null) {
				ArrayList<CPListElement> result= new ArrayList<>();
				for (int i= 0; i < paths.length; i++) {
					IPath path= paths[i];
					CPListElement elem= createCPVariableElement(path);
					if (!existingElements.contains(elem)) {
						elem.setModuleAttributeIf9OrHigher(fCurrJProject);
						result.add(elem);
					}
				}
				return result.toArray(new CPListElement[result.size()]);
			}
		} else {
			IPath path= BuildPathDialogAccess.configureVariableEntry(getShell(), existing.getPath(), existingPathsArray);
			if (path != null) {
				return new CPListElement[] { createCPVariableElement(path) };
			}
		}
		return null;
	}

	private CPListElement createCPVariableElement(IPath path) {
		CPListElement elem= new CPListElement(fCurrJProject, IClasspathEntry.CPE_VARIABLE, path, null);
		IPath resolvedPath= JavaCore.getResolvedVariablePath(path);
		elem.setIsMissing((resolvedPath == null) || !resolvedPath.toFile().exists());
		return elem;
	}

	private CPListElement[] openContainerSelectionDialog(CPListElement existing) {
		boolean shouldAddModule= false;
		if (this.getSelection().size() == 1) {
			Object obj= this.getSelection().get(0);
			if (obj instanceof RootCPListElement) {
				shouldAddModule= ((RootCPListElement) obj).isModulePathRootNode();
			}
		}
		if (existing == null) {
			IClasspathEntry[] created= BuildPathDialogAccess.chooseContainerEntries(getShell(), fCurrJProject, getRawClasspath());
			if (created != null) {
				CPListElement[] res= new CPListElement[created.length];
				for (int i= 0; i < res.length; i++) {
					res[i]= CPListElement.create(created[i], true, fCurrJProject);
					if (res[i].getClasspathEntry().getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
						if (!isJREContainer(res[i].getPath())) {
							res[i].updateExtraAttributeOfClasspathEntry();
						}
						if (!shouldAddModule) {
							res[i].setAttribute(CPListElement.MODULE, null);
						}
					}
				}
				return res;
			}
		} else {
			IClasspathEntry existingEntry= existing.getClasspathEntry();
			IClasspathEntry created= BuildPathDialogAccess.configureContainerEntry(getShell(), existingEntry, fCurrJProject, getRawClasspath());
			if (created != null) {
				CPListElement elem= new CPListElement(null, fCurrJProject, created, IClasspathEntry.CPE_CONTAINER, created.getPath(), null, ! created.equals(existingEntry), null, null);
				IVMInstall vmInstall= JavaRuntime.getVMInstall(created.getPath());
				if (vmInstall != null) {
					if(JavaRuntime.isModularJava(vmInstall)) {
						elem.updateExtraAttributeOfClasspathEntry();
					}
				}
				return new CPListElement[] { elem };
			}
		}
		return null;
	}

	private IClasspathEntry[] getRawClasspath() {
		IClasspathEntry[] currEntries= new IClasspathEntry[fClassPathList.getSize()];
		for (int i= 0; i < currEntries.length; i++) {
			CPListElement curr= fClassPathList.getElement(i);
			currEntries[i]= curr.getClasspathEntry();
		}
		return currEntries;
	}

	@Override
	public boolean isEntryKind(int kind) {
		return kind == IClasspathEntry.CPE_LIBRARY || kind == IClasspathEntry.CPE_VARIABLE || kind == IClasspathEntry.CPE_CONTAINER;
	}

	/*
	 * @see BuildPathBasePage#getSelection
	 */
	@Override
	public List<?> getSelection() {
		return fLibrariesList.getSelectedElements();
	}

	/*
	 * @see BuildPathBasePage#setSelection
	 */
	@Override
	public void setSelection(List<?> selElements, boolean expand) {
		fLibrariesList.selectElements(new StructuredSelection(selElements));
		if (expand) {
			for (int i= 0; i < selElements.size(); i++) {
				fLibrariesList.expandElement(selElements.get(i), 1);
			}
		}
	}

    @Override
	public void setFocus() {
    	fLibrariesList.setFocus();
    }

}
