1 /*******************************************************************************
2  * Copyright (c) 2006, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  ******************************************************************************/
14 
15 package org.eclipse.ui.internal.navigator.dnd;
16 
17 import java.util.ArrayList;
18 import java.util.LinkedHashSet;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.TreeMap;
23 
24 import org.eclipse.core.runtime.IConfigurationElement;
25 import org.eclipse.ui.internal.navigator.extensions.ExtensionSequenceNumberComparator;
26 import org.eclipse.ui.internal.navigator.extensions.INavigatorContentExtPtConstants;
27 import org.eclipse.ui.internal.navigator.extensions.NavigatorContentRegistryReader;
28 import org.eclipse.ui.navigator.INavigatorContentDescriptor;
29 import org.eclipse.ui.navigator.INavigatorContentService;
30 
31 /**
32  * @since 3.2
33  *
34  */
35 public class CommonDropDescriptorManager {
36 
37 	private static final CommonDropDescriptorManager INSTANCE = new CommonDropDescriptorManager();
38 
39 	private static final CommonDropAdapterDescriptor[] NO_DESCRIPTORS = new CommonDropAdapterDescriptor[0];
40 
41 	/**
42 	 * A map of (INavigatorContentDescriptor,
43 	 * CommonDropAdapterDescriptor)-pairs.
44 	 */
45 	private final Map<INavigatorContentDescriptor, List> dropDescriptors = new TreeMap<>(ExtensionSequenceNumberComparator.INSTANCE);
46 
47 	/**
48 	 *
49 	 * @return An initialized singleton instance of the
50 	 *         CommonDropDescriptorManager.
51 	 */
getInstance()52 	public static CommonDropDescriptorManager getInstance() {
53 		return INSTANCE;
54 	}
55 
CommonDropDescriptorManager()56 	private CommonDropDescriptorManager() {
57 		new CommonDropAdapterRegistry().readRegistry();
58 	}
59 
60 	/**
61 	 *
62 	 * @param aDropTarget
63 	 *            The drop target of the operation
64 	 * @param aContentService
65 	 *            The associated content service to filter results by.
66 	 * @return An array of drop descriptors that can handle the given drop
67 	 *         target and are <i>visible</i> and <i>active</i> for the given
68 	 *         service and <i>enabled</i> for the given drop target..
69 	 */
findCommonDropAdapterAssistants(Object aDropTarget, INavigatorContentService aContentService)70 	public CommonDropAdapterDescriptor[] findCommonDropAdapterAssistants(Object aDropTarget, INavigatorContentService aContentService) {
71 
72 		Set<CommonDropAdapterDescriptor> foundDescriptors = new LinkedHashSet<>();
73 		for (INavigatorContentDescriptor contentDescriptor : dropDescriptors.keySet()) {
74 			if (aContentService.isVisible(contentDescriptor.getId())
75 					&& aContentService.isActive(contentDescriptor.getId())) {
76 				List<CommonDropAdapterDescriptor> dropDescriptors = getDropDescriptors(contentDescriptor);
77 				for (CommonDropAdapterDescriptor dropDescriptor : dropDescriptors) {
78 					if (dropDescriptor.isDropElementSupported(aDropTarget)) {
79 						foundDescriptors.add(dropDescriptor);
80 					}
81 				}
82 			}
83 		}
84 
85 		if (foundDescriptors.isEmpty()) {
86 			return NO_DESCRIPTORS;
87 		}
88 		return foundDescriptors
89 				.toArray(new CommonDropAdapterDescriptor[foundDescriptors
90 						.size()]);
91 	}
92 
getDropDescriptors( INavigatorContentDescriptor aContentDescriptor)93 	private List<CommonDropAdapterDescriptor> getDropDescriptors(
94 			INavigatorContentDescriptor aContentDescriptor) {
95 		List<CommonDropAdapterDescriptor> descriptors = dropDescriptors.get(aContentDescriptor);
96 		if (descriptors != null) {
97 			return descriptors;
98 		}
99 		synchronized (dropDescriptors) {
100 			descriptors = dropDescriptors.get(aContentDescriptor);
101 			if (descriptors == null) {
102 				dropDescriptors.put(aContentDescriptor,
103 						(descriptors = new ArrayList<>()));
104 			}
105 
106 		}
107 		return descriptors;
108 	}
109 
110 	/**
111 	 * @param aContentDescriptor
112 	 *            A non-null content descriptor.
113 	 * @param aDropDescriptor
114 	 *            A non-null drop descriptor.
115 	 */
addCommonDropAdapter( INavigatorContentDescriptor aContentDescriptor, CommonDropAdapterDescriptor aDropDescriptor)116 	private void addCommonDropAdapter(
117 			INavigatorContentDescriptor aContentDescriptor,
118 			CommonDropAdapterDescriptor aDropDescriptor) {
119 		getDropDescriptors(aContentDescriptor).add(aDropDescriptor);
120 	}
121 
122 	private class CommonDropAdapterRegistry extends
123 			NavigatorContentRegistryReader implements
124 			INavigatorContentExtPtConstants {
125 
CommonDropAdapterRegistry()126 		private CommonDropAdapterRegistry() {
127 		}
128 
129 		@Override
readElement(IConfigurationElement element)130 		protected boolean readElement(IConfigurationElement element) {
131 
132 			if (TAG_NAVIGATOR_CONTENT.equals(element.getName())) {
133 
134 				String id = element.getAttribute(ATT_ID);
135 				if (id != null) {
136 					INavigatorContentDescriptor contentDescriptor = CONTENT_DESCRIPTOR_MANAGER
137 							.getContentDescriptor(id);
138 					if (contentDescriptor != null) {
139 
140 						IConfigurationElement[] commonDropAdapters = element
141 								.getChildren(TAG_COMMON_DROP_ADAPTER);
142 
143 						for (IConfigurationElement commonDropAdapter : commonDropAdapters) {
144 							addCommonDropAdapter(contentDescriptor,
145 									new CommonDropAdapterDescriptor(commonDropAdapter, contentDescriptor));
146 						}
147 					}
148 				}
149 
150 			}
151 			return super.readElement(element);
152 		}
153 
154 	}
155 
156 }
157