001 /* 002 * file ResourceSource.java 003 * 004 * Licensed Materials - Property of IBM 005 * Restricted Materials of IBM - you are allowed to copy, modify and 006 * redistribute this file as part of any program that interfaces with 007 * IBM Rational CM API. 008 * 009 * com.ibm.rational.teamapi.scout.ResourceSource 010 * 011 * © Copyright IBM Corporation 2004, 2008. All Rights Reserved. 012 * Note to U.S. Government Users Restricted Rights: Use, duplication or 013 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 014 */ 015 package com.ibm.rational.teamapi.scout; 016 017 import java.lang.reflect.Array; 018 import java.util.List; 019 020 import javax.wvcm.PropertyRequestItem; 021 import javax.wvcm.WvcmException; 022 import javax.wvcm.PropertyNameList.PropertyName; 023 import javax.wvcm.PropertyRequestItem.PropertyRequest; 024 025 import org.eclipse.swt.custom.BusyIndicator; 026 import org.eclipse.swt.widgets.Display; 027 import org.eclipse.ui.views.properties.IPropertyDescriptor; 028 import org.eclipse.ui.views.properties.IPropertySheetEntry; 029 import org.eclipse.ui.views.properties.PropertyDescriptor; 030 031 import com.ibm.rational.wvcm.stp.StpLocation; 032 import com.ibm.rational.wvcm.stp.StpProperty; 033 import com.ibm.rational.wvcm.stp.StpPropertyException; 034 import com.ibm.rational.wvcm.stp.StpResource; 035 import com.ibm.rational.wvcm.stp.StpProperty.MetaPropertyName; 036 037 038 /** 039 * An implementation of IPropertySource for displaying the properties of a CM 040 * API Resource. ProperyName objects are used for the property identifiers. 041 */ 042 public class ResourceSource 043 extends DefaultPropertySource 044 { 045 /** 046 * Requests all properties from the server and then constructs a property 047 * descriptor for each property returned. For efficiently, the descriptors 048 * are cached after the properties are read from the resource. The 049 * possibility of displaying stale data could be avoided by re-reading the 050 * properties each time the descriptors are requested. 051 * 052 * @return An array of ResourcePropertyDescriptors, one for each property 053 * of the resource represented by this object. 054 */ 055 public IPropertyDescriptor[] getPropertyDescriptors() 056 { 057 if (m_descriptors == null) { 058 try { 059 // At the top level some pseudo-resources are used to represent 060 // requests for folder lists. Properties should not be requested 061 // from these. 062 StpLocation selector = m_resource.stpLocation(); 063 String name = selector.getName(); 064 String server = ""; 065 String repo = selector.getRepo(); 066 067 if ((name == null || name.length() == 0) 068 && (repo == null || repo.length() == 0) 069 && (server != null && server.length() > 0)) { 070 return null; 071 } 072 073 // This may take a while, so run it off the UI thread and 074 // put up a wait cursor. 075 final Display display = Display.getCurrent(); 076 final Runnable longJob = 077 new Runnable() { 078 boolean m_done = false; 079 080 public void run() 081 { 082 Thread thread = new Thread(new Runnable() { 083 public void run() 084 { 085 try { 086 m_resource = 087 (StpResource)m_resource 088 .doReadProperties( 089 WANTED_PROPS); 090 } catch (WvcmException e) { 091 e.printStackTrace(); 092 } 093 m_done = true; 094 } 095 }); 096 thread.start(); 097 098 while (!m_done) { 099 if (!display.readAndDispatch()) 100 display.sleep(); 101 } 102 } 103 }; 104 105 BusyIndicator.showWhile(display, longJob); 106 107 // Get a list of all the properties returned in the new proxy. 108 StpProperty.List properties = 109 (StpProperty.List)m_resource.getAllProperties(); 110 111 m_descriptors = new IPropertyDescriptor[properties.size()]; 112 113 for (int i = 0; i < m_descriptors.length; ++i) { 114 Object property = properties.get(i); 115 116 // The StpProperty.List will contain a PropertyException if 117 // the requested property could not be returned from the 118 // resource; a StpProperty object otherwise. A different 119 // variant of ResourcePropertyDescriptor is used for each 120 // case. 121 if (property instanceof StpProperty) 122 m_descriptors[i] = 123 new ResourcePropertyDescriptor((StpProperty) 124 property, 125 m_resource); 126 else 127 m_descriptors[i] = 128 new ResourcePropertyDescriptor( 129 (StpPropertyException)property, 130 m_resource); 131 } 132 } catch (Throwable ex) { 133 ex.printStackTrace(); 134 } 135 } 136 137 return m_descriptors; 138 } 139 140 /** 141 * Retrieves the value of a property from the resource proxy. Compound 142 * values are wrapped by a type-specific PropertySource for viewing the 143 * values. 144 * 145 * @param id The property identifier, which, in this case, is the 146 * PropertyName of the CM API property. 147 * 148 * @return Either a PropertySource (for compound values) or the value 149 * itself. 150 */ 151 public Object getPropertyValue(Object id) 152 { 153 Object val = m_resource.lookupProperty((PropertyName)id); 154 155 return getPropertySource(val); 156 } 157 158 /** 159 * Constructs a ResourceSource object for displaying the properties of a 160 * resource identified by a Resource proxy. 161 * 162 * @param resource A Resource proxy for the resource whose properties are 163 * to be displayed. 164 */ 165 ResourceSource(StpResource resource) 166 { 167 m_resource = resource; 168 } 169 170 /** 171 * The proxy for the resource whose properties are displayed by this source 172 */ 173 protected StpResource m_resource; 174 175 /** The cached property descriptors for the properties read. */ 176 IPropertyDescriptor[] m_descriptors = null; 177 178 /** The PropertyRequest used to request all properties from the resource */ 179 static final PropertyRequest WANTED_PROPS = 180 new PropertyRequest( 181 new PropertyRequestItem[] {StpResource.ALL_PROPERTIES.nest( 182 new PropertyRequestItem[] {StpProperty.VALUE.nest( 183 new PropertyRequestItem[] { 184 StpProperty.NAME, 185 StpProperty.TYPE, 186 StpProperty.VALUE 187 })})}); 188 189 /** The value used to flag properties with errors */ 190 static final String[] ADVANCED_PROPERTY_FLAGS = 191 new String[] {IPropertySheetEntry.FILTER_ID_EXPERT}; 192 193 /** 194 * A PropertyDescriptor for CM API resource properties. 195 */ 196 static class ResourcePropertyDescriptor 197 extends PropertyDescriptor 198 { 199 /** 200 * Constructs a PropertyDescriptor for a StpProperty successfully 201 * retrieved from a proxy. If the VALUE meta-property of the StpProperty 202 * is inaccessible, the property is marked as one for expert viewing 203 * only. 204 * 205 * @param property The StpProperty 206 * @param parent The resource from which the StpProperty came. 207 */ 208 ResourcePropertyDescriptor( 209 StpProperty property, 210 StpResource parent) 211 { 212 super(property.getPropertyName(), 213 property.getPropertyName().getName()); 214 m_propertyName = property.getPropertyName(); 215 216 try { 217 property.getValue(); 218 } catch (WvcmException ex) { 219 m_filter_flags = ADVANCED_PROPERTY_FLAGS; 220 } 221 222 try { 223 setDescription(property.getType() + " property of " 224 + parent.location().string()); 225 } catch (WvcmException ex) { 226 setDescription("Untyped property of " 227 + parent.location().string()); 228 } 229 } 230 231 /** 232 * Constructs a PropertyDescriptor for a PropertyException received 233 * while attempting to retrieve a StpProperty from a proxy. The property 234 * is marked as one for expert viewing only. 235 * 236 * @param property The PropertyException 237 * @param parent The resource from which the StpProperty came. 238 */ 239 ResourcePropertyDescriptor( 240 StpPropertyException property, 241 StpResource parent) 242 { 243 super(property.getPropertyName(), 244 property.getPropertyName().getName()); 245 m_propertyName = property.getPropertyName(); 246 m_filter_flags = ADVANCED_PROPERTY_FLAGS; 247 setDescription("inaccessible property of " 248 + parent.location().string()); 249 } 250 251 /** 252 * Returns the Namespace of the PropertyName for the property to use as 253 * a category for organizing the properties of the resource. 254 * 255 * @return A String containing the simple name of the namespace of the 256 * property name. 257 */ 258 public String getCategory() 259 { 260 String category = m_propertyName.getNamespace(); 261 262 if (category == null) 263 category = "WVCM"; 264 else { 265 int slash = category.lastIndexOf("/"); 266 267 if (slash > 0) 268 category = category.substring(slash + 1); 269 } 270 271 return category; 272 } 273 274 /** 275 * Returns ADVANCED_PROPERTY_FLAGS for properties that could not be read 276 * from the resource; null otherwise; 277 * 278 * @see org.eclipse.ui.views.properties.PropertyDescriptor#getFilterFlags() 279 */ 280 public String[] getFilterFlags() 281 { 282 return m_filter_flags; 283 } 284 285 /** The PropertyName for the property */ 286 PropertyName m_propertyName; 287 288 /** The value of getFilterFlags() */ 289 String[] m_filter_flags = super.getFilterFlags(); 290 } 291 292 /** 293 * A PropertySource for displaying properties whose value is a list. 294 */ 295 static class ListSource 296 extends DefaultPropertySource 297 { 298 /** 299 * Constructs a new ListSource for a List value. 300 * 301 * @param list The value that is to be displayed by this 302 * PropertySource 303 */ 304 ListSource(List list) 305 { 306 m_list = list; 307 } 308 309 /** 310 * Computes and returns an array of PropertyDescriptors, one descriptor 311 * per element of the list. An Integer object representing the ordinal 312 * position of the element in the list is used as the property id. 313 * 314 * @return An array of PropertyDescriptors for the elements of the 315 * ResourceList value of this property. 316 */ 317 public IPropertyDescriptor[] getPropertyDescriptors() 318 { 319 IPropertyDescriptor[] result = 320 new IPropertyDescriptor[m_list.size()]; 321 322 for (int i = 0; i < result.length; ++i) { 323 String name = getDisplayName(m_list.get(i), i); 324 325 result[i] = new PropertyDescriptor(new Integer(i), name); 326 ((PropertyDescriptor)result[i]).setDescription(m_list.getClass() 327 .getName() + " item"); 328 } 329 330 return result; 331 } 332 333 /** 334 * Retrieves the List item identified by a given property identifier. 335 * 336 * @param id An Integer representing the ordinal position of the item 337 * in the list 338 * 339 * @return The value at the given index, wrapped in a PropertySource if 340 * the item is a composite object such as a Resource, List, or 341 * Array. 342 */ 343 public Object getPropertyValue(Object id) 344 { 345 return getPropertySource(m_list.get(((Integer)id).intValue())); 346 } 347 348 /** The List that this PropertySource will be displaying */ 349 List m_list; 350 } 351 352 /** 353 * A PropertySource for displaying properties whose value is an array. 354 */ 355 static class ArraySource 356 extends DefaultPropertySource 357 { 358 /** 359 * Constructs an ArraySource for an array value 360 * 361 * @param array The array to be displayed by the ArraySource. 362 */ 363 ArraySource(Object array) 364 { 365 m_array = array; 366 } 367 368 /** 369 * Computes and returns an array of PropertyDescriptors, one descriptor 370 * per element of the array. An Integer object representing the ordinal 371 * position of the element in the array is used as the property id. 372 * 373 * @return An array of PropertyDescriptors for the elements of this 374 * array-valued property. 375 */ 376 public IPropertyDescriptor[] getPropertyDescriptors() 377 { 378 IPropertyDescriptor[] result = 379 new IPropertyDescriptor[Array.getLength(m_array)]; 380 381 for (int i = 0; i < result.length; ++i) { 382 String name = getDisplayName(Array.get(m_array, i), i); 383 384 result[i] = new PropertyDescriptor(new Integer(i), name); 385 } 386 387 return result; 388 } 389 390 /** 391 * Retrieves the array element identified by a given property 392 * identifier. 393 * 394 * @param id An Integer representing the index of the item in the 395 * array 396 * 397 * @return The value at the given index, wrapped in a PropertySource if 398 * the item is a composite object such as a Resource, List, or 399 * Array. 400 */ 401 public Object getPropertyValue(Object id) 402 { 403 return getPropertySource(Array.get( 404 m_array, 405 ((Integer)id).intValue())); 406 } 407 408 /** The array of values represented by this PropertySource */ 409 Object m_array; 410 } 411 412 /** 413 * A PropertySource for displaying properties whose value is a StpProperty. 414 */ 415 static class PropertySource 416 extends DefaultPropertySource 417 { 418 /** 419 * Constructs a PropertySource for a StpProperty. 420 * 421 * @param property The StpProperty object to be displayed by this 422 * PropertySource 423 */ 424 PropertySource(StpProperty property) 425 { 426 m_property = property; 427 } 428 429 /** 430 * Computes and returns an array of PropertyDescriptors, one descriptor 431 * per meta-property defined by the StpProperty. A MetaPropertyName 432 * object is used as the property id. 433 * 434 * @return An array of PropertyDescriptors for the meta-properties 435 * defined for this property. 436 */ 437 public IPropertyDescriptor[] getPropertyDescriptors() 438 { 439 MetaPropertyName[] metaProps = m_property.metaPropertyNames(); 440 IPropertyDescriptor[] result = 441 new IPropertyDescriptor[metaProps.length]; 442 443 for (int i = 0; i < result.length; ++i) { 444 result[i] = 445 new PropertyDescriptor(metaProps[i], metaProps[i].getName()); 446 } 447 448 return result; 449 } 450 451 /** 452 * Retrieves the meta-property identified by a given property 453 * identifier. 454 * 455 * @param id A MetaPropertyName identifying a meta-property of the 456 * StpProperty. 457 * 458 * @return The value of the given meta-property, wrapped in a 459 * PropertySource if the item is a composite object such as a 460 * Resource, StpProperty, List, or Array. 461 */ 462 public Object getPropertyValue(Object id) 463 { 464 try { 465 MetaPropertyName<?> name = (MetaPropertyName<?>)id; 466 Object prop = m_property.getMetaProperty(name); 467 468 return getPropertySource(prop); 469 } catch (WvcmException ex) { 470 return ex; 471 } 472 } 473 474 /** The StpProperty being displayed by this PropertySource */ 475 StpProperty<?> m_property; 476 } 477 478 /** 479 * Selects a possible PropertySource for a given value based on the data 480 * type of the value. A PropertySource is used for a value that is a 481 * Resource, StpProperty, List (including ResourceList or StpProperty.List), 482 * or an array. 483 * 484 * @param val The value to be displayed 485 * 486 * @return The input value or an appropriate PropertySource for it. 487 */ 488 private static Object getPropertySource(Object val) 489 { 490 if (val != null) { 491 if (val instanceof List) 492 val = new ListSource((List)val); 493 else if (val instanceof StpResource) 494 val = new ResourceSource((StpResource)val); 495 else if (val.getClass().isArray()) 496 val = new ArraySource(val); 497 else if (val instanceof StpProperty) 498 val = new PropertySource((StpProperty)val); 499 else if (val instanceof PropertyName) { 500 PropertyName pn = (PropertyName)val; 501 String space = pn.getNamespace(); 502 503 val = pn.getName() + (space == null ? "" : " in " + space); 504 } 505 } 506 507 return val; 508 } 509 510 /** 511 * Constructs an appropriate display name for an item in a compound value. 512 * 513 * @param item The item to be displayed 514 * @param index the index of the item in it's list. 515 * 516 * @return A String containing a display name for the item. 517 */ 518 private static String getDisplayName( 519 Object item, 520 int index) 521 { 522 String name = " " + Integer.toString(index); 523 524 if (item instanceof StpResource) 525 name = ((StpResource)item).location().lastSegment(); 526 else if (item instanceof StpProperty) 527 name = ((StpProperty)item).getPropertyName().getName(); 528 else 529 name = name.substring(name.length() - 5); 530 531 return name; 532 } 533 }