1
/*******************************************************************************
2
* Copyright (c) 2010 Wind River Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Wind River Systems - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.dsf.ui.viewmodel.properties;
13
import java.util.Collection;
14
import java.util.HashMap;
15
import java.util.HashSet;
19
import org.eclipse.cdt.dsf.concurrent.DsfMultiStatus;
20
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
21
import org.eclipse.core.runtime.IStatus;
24
* Status object for use with the IPropertiesUpdate. This status class
25
* allows setting a different status result for each property. This allows
26
* for better interpretation of status by the client of the update.
28
* This status class derives from MultiStatus class such that the status
29
* objects for each property can be accessed through the standard
30
* {@link #getChildren()} method. Also, multiple properties can reference
31
* the same status object, meaning that the number of properties returned
32
* by {@link #getProperties()} may be greater than the status objects
33
* returned by <code>getChildren()</code>.
35
* The properties status object does not have its own message, severity,
36
* error status or exception. All these attributes are calculated from
37
* the child status objects. If the status has more than one status child,
38
* the String returned by {@link #getMessage()} is: "Multiple errors reported".
42
public class PropertiesUpdateStatus extends DsfMultiStatus {
44
final private Map<String,IStatus> fPropertiesStatus = new HashMap<String, IStatus>(1);
45
private boolean fFirstStatusSet;
47
public PropertiesUpdateStatus() {
48
super(DsfUIPlugin.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
52
* Returns set of properties that have an additional status specified.
54
public Set<String> getProperties() {
55
return fPropertiesStatus.keySet();
59
* Returns an additional status for the given property in a property
60
* update. Returned value may be <code>null</code> if no additional
63
public IStatus getStatus(String property) {
64
return fPropertiesStatus.get(property);
68
* Sets the given status for the given property.
70
public void setStatus(String property, IStatus status) {
71
IStatus child = findEquivalentChild(status);
78
fPropertiesStatus.put(property, status);
82
* Sets the given status for the properties array.
84
public void setStatus(String[] properties, IStatus status) {
85
IStatus child = findEquivalentChild(status);
92
for (String property : properties) {
93
fPropertiesStatus.put(property, status);
98
* Merges data in the new status into the base status data, and returns the
99
* resulting status. Only properties specified in the given set are merged.
101
* The new status is considered to be more up to date than the base
102
* status and its data overrides the base status . If the base status
103
* holds an error for a given property, which is found in the
104
* given set, and the new status does not, then the base error status is
107
* @param baseStatus Properties into which the new status properties will
109
* @param newStatus Properties status to merge.
110
* @param properties The properties to consider in the new status.
111
* @return Resulting merged status object.
113
public static PropertiesUpdateStatus mergePropertiesStatus(PropertiesUpdateStatus baseStatus,
114
PropertiesUpdateStatus newStatus, Set<String> properties)
116
PropertiesUpdateStatus mergedStatus = new PropertiesUpdateStatus();
117
// Copy the property status map from the base status.
118
mergedStatus.fPropertiesStatus.putAll(baseStatus.fPropertiesStatus);
120
// Add in the property statuses from the new status, but only for the
121
// specified properties.
122
for (String property : properties) {
123
IStatus propertyStatus = newStatus.getStatus(property);
124
if (propertyStatus != null) {
125
mergedStatus.fPropertiesStatus.put(property, propertyStatus);
127
mergedStatus.fPropertiesStatus.remove(property);
131
// Children of merged status should contain all statuses that are found in the fPropertiesStatus map, but
132
// without duplicates.
133
Set<IStatus> children = new HashSet<IStatus>((baseStatus.getChildren().length + newStatus.getChildren().length) * 4/3);
134
children.addAll(mergedStatus.fPropertiesStatus.values());
135
for (IStatus child : children) {
136
mergedStatus.add(child);
139
// Merged status should contain all children statuses that were added without a corresponding property to the
140
// base status and to the new status.
141
Collection<IStatus> baseStatusPropertyChildren = baseStatus.fPropertiesStatus.values();
142
for (IStatus baseStatusChild : baseStatus.getChildren()) {
143
if (!baseStatusPropertyChildren.contains(baseStatusChild)) {
144
mergedStatus.add(baseStatusChild);
147
Collection<IStatus> newStatusPropertyChildren = newStatus.fPropertiesStatus.values();
148
for (IStatus newStatusChild : newStatus.getChildren()) {
149
if (!newStatusPropertyChildren.contains(newStatusChild)) {
150
mergedStatus.add(newStatusChild);
158
* Adds the given status object as a child of this status. If there's an
159
* equivalent child status already, the new status is ignored.
162
public void add(IStatus status) {
163
if (findEquivalentChild(status) != null) {
171
firstSet = fFirstStatusSet;
172
fFirstStatusSet = true;
176
setMessage(status.getMessage());
178
setMessage(MessagesForProperties.PropertiesUpdateStatus_message);
183
* Finds a child status that is equivalent to the given status.
185
private IStatus findEquivalentChild(IStatus status) {
186
if (getChildren().length != 0) {
187
for (IStatus child : getChildren()) {
188
if (areEquivalent(child, status)) {
197
* Compares two status objects to determine if they are equivalent.
199
private boolean areEquivalent(IStatus s1, IStatus s2) {
200
if ( (s1 == null && s2 != null) || (s1 != null && s2 == null) )
207
if ( (s1.getSeverity() != s2.getSeverity()) ||
208
!s1.getPlugin().equals(s2.getPlugin()) ||
209
(s1.getCode() != s2.getCode()) )
213
if ( (s1.getException() == null && s1.getException() != null) ||
214
(s1.getException() != null && s1.getException() == null) ||
215
(s1.getException() != null && !s1.getException().equals(s2.getException())) )
219
return s1.getMessage().equals(s2.getMessage());
223
* Convenience method that returns and optionally creates a properties
224
* update status object for the given update.
226
public static PropertiesUpdateStatus getPropertiesStatus(IPropertiesUpdate update) {
227
IStatus updateStatus = update.getStatus();
228
if (updateStatus instanceof PropertiesUpdateStatus) {
229
return (PropertiesUpdateStatus)updateStatus;
231
PropertiesUpdateStatus propertiesStatus = new PropertiesUpdateStatus();
232
update.setStatus(propertiesStatus);
233
if (!updateStatus.isOK()) {
234
propertiesStatus.add(updateStatus);
236
return propertiesStatus;
241
* Convenience method that returns and optionally creates a properties
242
* update status object for the given update.
244
public static PropertiesUpdateStatus makePropertiesStatus(IStatus updateStatus) {
245
if (updateStatus instanceof PropertiesUpdateStatus) {
246
return (PropertiesUpdateStatus)updateStatus;
248
PropertiesUpdateStatus propertiesStatus = new PropertiesUpdateStatus();
249
if (!updateStatus.isOK()) {
250
propertiesStatus.add(updateStatus);
252
return propertiesStatus;