1 /*******************************************************************************
2  * Copyright (c) 2000, 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  package org.eclipse.ltk.internal.ui.refactoring;
15 
16 import java.util.ArrayList;
17 import java.util.List;
18 
19 import org.eclipse.core.runtime.Assert;
20 import org.eclipse.core.runtime.CoreException;
21 
22 import org.eclipse.jface.text.IRegion;
23 
24 import org.eclipse.ltk.core.refactoring.Change;
25 import org.eclipse.ltk.core.refactoring.GroupCategory;
26 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
27 import org.eclipse.ltk.core.refactoring.TextEditBasedChange;
28 import org.eclipse.ltk.core.refactoring.TextEditBasedChangeGroup;
29 import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer;
30 import org.eclipse.ltk.ui.refactoring.TextEditChangeNode;
31 import org.eclipse.ltk.ui.refactoring.TextEditChangeNode.ChildNode;
32 
33 public abstract class InternalLanguageElementNode extends TextEditChangeNode.ChildNode {
34 
35 	private List<ChildNode> fChildren;
36 	private GroupCategorySet fGroupCategories;
37 
InternalLanguageElementNode(PreviewNode parent)38 	protected InternalLanguageElementNode(PreviewNode parent) {
39 		super(parent);
40 	}
41 
42 	@Override
getChangePreviewViewerDescriptor()43 	ChangePreviewViewerDescriptor getChangePreviewViewerDescriptor() throws CoreException {
44 		InternalTextEditChangeNode element= getTextEditChangeNode();
45 		if (element == null)
46 			return null;
47 		return element.getChangePreviewViewerDescriptor();
48 	}
49 
50 	@Override
feedInput(IChangePreviewViewer viewer, List<GroupCategory> categories)51 	void feedInput(IChangePreviewViewer viewer, List<GroupCategory> categories) throws CoreException {
52 		InternalTextEditChangeNode element= getTextEditChangeNode();
53 		if (element != null) {
54 			Change change= element.getChange();
55 			if (change instanceof TextEditBasedChange) {
56 				List<TextEditBasedChangeGroup> groups= collectTextEditBasedChangeGroups(categories);
57 				viewer.setInput(TextEditChangePreviewViewer.createInput(change,
58 					groups.toArray(new TextEditBasedChangeGroup[groups.size()]),
59 					getTextRange()));
60 			}
61 		} else {
62 			viewer.setInput(null);
63 		}
64 	}
65 
66 	@Override
setEnabled(boolean enabled)67 	void setEnabled(boolean enabled) {
68 		for (PreviewNode element : fChildren) {
69 			element.setEnabled(enabled);
70 		}
71 	}
72 
73 	@Override
setEnabledShallow(boolean enabled)74 	void setEnabledShallow(boolean enabled) {
75 		// do nothing. We don't manage an own enablement state.
76 	}
77 
78 	@Override
getActive()79 	int getActive() {
80 		Assert.isTrue(fChildren.size() > 0);
81 		int result= ((PreviewNode)fChildren.get(0)).getActive();
82 		for (int i= 1; i < fChildren.size(); i++) {
83 			PreviewNode element= fChildren.get(i);
84 			result= PreviewNode.ACTIVATION_TABLE[element.getActive()][result];
85 			if (result == PreviewNode.PARTLY_ACTIVE)
86 				break;
87 		}
88 		return result;
89 	}
90 
91 	@Override
getChildren()92 	PreviewNode[] getChildren() {
93 		if (fChildren == null)
94 			return PreviewNode.EMPTY_CHILDREN;
95 		return fChildren.toArray(new PreviewNode[fChildren.size()]);
96 	}
97 
98 	@Override
hasOneGroupCategory(List<GroupCategory> categories)99 	boolean hasOneGroupCategory(List<GroupCategory> categories) {
100 		if (fChildren == null)
101 			return false;
102 		return getGroupCategorySet().containsOneCategory(categories);
103 	}
104 
105 	@Override
hasDerived()106 	boolean hasDerived() {
107 		if (fChildren == null)
108 			return false;
109 		for (PreviewNode node : fChildren) {
110 			if (node.hasDerived())
111 				return true;
112 		}
113 		return false;
114 	}
115 
getGroupCategorySet()116 	private GroupCategorySet getGroupCategorySet() {
117 		if (fGroupCategories == null) {
118 			fGroupCategories= GroupCategorySet.NONE;
119 			for (PreviewNode node : fChildren) {
120 				GroupCategorySet other= null;
121 				if (node instanceof TextEditGroupNode) {
122 					other= ((TextEditGroupNode)node).getGroupCategorySet();
123 				} else if (node instanceof InternalLanguageElementNode) {
124 					other= ((InternalLanguageElementNode)node).getGroupCategorySet();
125 				} else {
126 					Assert.isTrue(false, "Shouldn't happen"); //$NON-NLS-1$
127 				}
128 				fGroupCategories= GroupCategorySet.union(fGroupCategories, other);
129 			}
130 		}
131 		return fGroupCategories;
132 	}
133 
internalAddChild(ChildNode child)134 	protected void internalAddChild(ChildNode child) {
135 		if (fChildren == null)
136 			fChildren= new ArrayList<>(2);
137 		fChildren.add(child);
138 	}
139 
collectTextEditBasedChangeGroups(List<GroupCategory> categories)140 	private List<TextEditBasedChangeGroup> collectTextEditBasedChangeGroups(List<GroupCategory> categories) {
141 		List<TextEditBasedChangeGroup> result= new ArrayList<>(10);
142 		for (PreviewNode child : getChildren()) {
143 			if (child instanceof TextEditGroupNode) {
144 				TextEditBasedChangeGroup changeGroup= ((TextEditGroupNode)child).getChangeGroup();
145 				if (categories == null || changeGroup.getGroupCategorySet().containsOneCategory(categories))
146 					result.add(changeGroup);
147 			} else if (child instanceof InternalLanguageElementNode) {
148 				result.addAll(((InternalLanguageElementNode)child).collectTextEditBasedChangeGroups(categories));
149 			}
150 		}
151 		return result;
152 	}
153 
154 	/**
155 	 * Returns the text region the of this language element node.
156 	 *
157 	 * @return the text region of this language element node
158 	 * @throws CoreException if the source region can't be obtained
159 	 */
getTextRange()160 	public abstract IRegion getTextRange() throws CoreException;
161 }
162