1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * ident "%Z%%M% %I% %E% SMI" 24 * 25 * Copyright (c) 2000 by Sun Microsystems, Inc. 26 * All rights reserved. 27 */ 28 29 /* 30 * Copyright (C) 1996 Active Software, Inc. 31 * All rights reserved. 32 * 33 * @(#) AMConverter.java 1.63 - last change made 06/25/97 34 */ 35 36 package sunsoft.jws.visual.rt.type; 37 38 import sunsoft.jws.visual.rt.base.Global; 39 40 import sunsoft.jws.visual.rt.base.*; 41 import sunsoft.jws.visual.rt.shadow.java.awt.*; 42 import sunsoft.jws.visual.rt.awt.CardPanel; 43 import sunsoft.jws.visual.rt.shadow.CardPanelShadow; 44 import java.util.*; 45 46 /** 47 * This class can convert attribute managment trees to strings and 48 * such strings back again to attribute management trees. The string 49 * produced is a complete description of an application, and so it can 50 * be used to save a tree to a file. 51 * 52 * @see AttributeManager 53 * @version 1.63, 06/25/97 54 */ 55 public class AMConverter extends Converter { 56 57 private static AttributeListConverter attrlistconv = 58 new AttributeListConverter(); 59 AMConverter()60 public AMConverter() { 61 } 62 63 /** 64 * List of paths (package prefixes) to groups of Shadow classes 65 * also a few individual Shadow classes. The Hashtables are for 66 * caching the matches after they are discovered. 67 */ 68 private static Vector shadows = new Vector(); 69 private static Hashtable shortShadowKeyed = new Hashtable(); 70 private static Hashtable longShadowKeyed = new Hashtable(); 71 72 /** 73 * Caches the matches after they are discovered. 74 */ cacheShadowPair(String shortName, String longName)75 private static void cacheShadowPair(String shortName, 76 String longName) { 77 shortShadowKeyed.put(shortName, longName); 78 longShadowKeyed.put(longName, shortName); 79 } 80 81 /** 82 * Adds the name of a package where custom shadow 83 * classes can be found. 84 * Package names in this list always end with a "." 85 */ addShadowPath(String pkgName)86 private static void addShadowPath(String pkgName) { 87 if (pkgName.endsWith(/* NOI18N */".")) 88 shadows.addElement(pkgName); 89 else 90 shadows.addElement(/* NOI18N */(pkgName + ".")); 91 } 92 93 /** 94 * Adds a specific shadow class to the list. 95 * Specific shadow classes 96 * in the list never end with a "." 97 */ addShadowItem(String className)98 private static void addShadowItem(String className) { 99 cacheShadowPair(Converter.shortClassName(className), 100 className); 101 } 102 103 static { 104 // add packages where shadow classes might be found 105 // 106 // Don't add any more of these or the quick 107 // code generation will 108 // be screwed! 109 addShadowPath(/* NOI18N */"sunsoft.jws.visual.rt.shadow"); 110 111 // add individual exceptions 112 addShadowItem 113 (/* NOI18N */"sunsoft.jws.visual.rt.base.Root"); 114 } 115 116 /** 117 * Figures out the short name for a shadow class. Removes the 118 * initial component of a class name if it's one of the currently 119 * listed paths for finding shadow classes. The result is the 120 * abbreviated name for the shadow class that can be placed in the 121 * save file. 122 * 123 * Warning: you should not nest shadow packages in the path within 124 * each other, as this routine might return the wrong shortened 125 * form 126 * of the class name. 127 */ shortenShadowPath(String longClassName)128 private static String shortenShadowPath(String longClassName) { 129 // return the cached value if available 130 if (longShadowKeyed.containsKey(longClassName)) 131 return ((String) longShadowKeyed.get(longClassName)); 132 /* JSTYLED */ 133 for (Enumeration e = shadows.elements(); e.hasMoreElements(); ) { 134 String s = (String) e.nextElement(); 135 if (longClassName.startsWith(s)) 136 return (longClassName.substring(s.length())); 137 } 138 139 // the long class name was not found in any of the paths 140 return (longClassName); 141 } 142 143 /** 144 * Searches the currently listed shadow paths for the shadow class 145 * given. Returns a runtime class reference to the shadow class 146 * once it finds that class under one of the paths (or, in the end, 147 * under the actual name given.) 148 * 149 * This is basically the reverse of shortenShadowPath. 150 */ searchShadowPath(String shortClassName)151 private static Class searchShadowPath(String shortClassName) { 152 // return the cached value if available 153 if (shortShadowKeyed.containsKey(shortClassName)) { 154 try { 155 return (Global.util.getClassLoader().loadClass 156 ((String) shortShadowKeyed.get 157 (shortClassName))); 158 } 159 catch (ClassNotFoundException ex) { 160 // that didn't work, silently try something else... 161 } 162 } 163 164 Class retval = null; 165 /* JSTYLED */ 166 for (Enumeration e = shadows.elements(); e.hasMoreElements(); ) { 167 String path = (String) e.nextElement(); 168 try { 169 retval = Global.util.getClassLoader().loadClass 170 (path + shortClassName); 171 break; 172 } 173 catch (ClassNotFoundException ex) { 174 // that didn't work, silently try again... 175 } 176 } 177 178 if (retval == null) { 179 try { 180 retval = Global.util.getClassLoader().loadClass 181 (shortClassName); 182 } 183 catch (ClassNotFoundException ex) { 184 // that didn't work either, how sad 185 throw new ParseException(Global.fmtMsg 186 ("sunsoft.jws.visual.rt.type.AMConverter.FMT.0", 187 Global.newline(), /* NOI18N */"\t", 188 ex.toString())); 189 } 190 } 191 192 // cache this pairing so it won't have to be looked up again 193 if (retval != null && !shortShadowKeyed.containsKey 194 (shortClassName)) 195 cacheShadowPair(retval.getName(), shortClassName); 196 197 return (retval); 198 } 199 200 /** 201 * Creates a string from the reference to the root or branch of the 202 * attribute management tree given. Appends the string to the given 203 * string buffer. 204 * 205 * @param obj attribute management tree reference 206 * @param buf string buffer to append to 207 * @return string that describes the tree 208 */ convertToString(Object obj, StringBuffer buf)209 public void convertToString(Object obj, StringBuffer buf) { 210 if (obj == null) 211 return; 212 213 // Make sure the first card is showing before saving the card panel. 214 if (obj instanceof CardPanelShadow) { 215 CardPanel cardPanel = (CardPanel) 216 ((CardPanelShadow)obj).getCardPanel(); 217 if (cardPanel != null) 218 cardPanel.first(); 219 } 220 221 AttributeManager tree = (AttributeManager) obj; 222 223 // 224 // Skip over any windows that are marked as panels. 225 // 226 /* JSTYLED */ 227 if ((tree instanceof WindowShadow) && ((WindowShadow)tree).isPanel()) { 228 AttributeManager child = ((WindowShadow)tree).getPanel(); 229 if (child != null) 230 convertToString(child, buf); 231 return; 232 } 233 234 // this object's own attributes 235 indent(buf); 236 buf.append(shortenShadowPath(tree.getClass().getName())); 237 buf.append(/* NOI18N */" "); 238 239 ListParser.quote(tree.getName(), buf, false); 240 241 buf.append(/* NOI18N */" {"); 242 newline(buf); 243 incrIndent(); 244 attrlistconv.convertToString(tree.getAttributeList(), buf); 245 decrIndent(); 246 247 // children 248 if (tree instanceof AMContainer) { 249 Enumeration e = ((AMContainer) tree).getChildList(); 250 AttributeManager child; 251 252 if (e.hasMoreElements()) { 253 incrIndent(); 254 indent(buf); 255 buf.append(/* NOI18N */"child list {"); 256 newline(buf); 257 258 incrIndent(); 259 while (e.hasMoreElements()) { 260 child = (AttributeManager) e.nextElement(); 261 convertToString(child, buf); 262 } 263 decrIndent(); 264 265 indent(buf); 266 buf.append(/* NOI18N */"}"); 267 newline(buf); 268 decrIndent(); 269 } 270 } 271 272 indent(buf); 273 buf.append(/* NOI18N */"}"); 274 newline(buf); 275 } 276 277 /** 278 * Call the convertFromString function that takes a version number 279 * instead. Tree conversion cannot take place without a version 280 * number (for the string description.) 281 * 282 * @exception Error when an attempt is made to call this method 283 */ convertFromString(String s)284 public Object convertFromString(String s) { 285 throw new Error(Global.getMsg( 286 /* JSTYLED */ 287 "sunsoft.jws.visual.rt.type.AMConverter.AMConverter__convertF.0")); 288 } 289 290 /** 291 * Creates a new tree based upon the description string given. 292 * There should only be one object (as the root of the tree) in the 293 * string. That root object may contain other objects, or children, 294 * as it were. 295 * 296 * @param version the version number for the gui description string 297 * @param s the string to convert to a tree @return new shadow tree 298 * @exception ParseException when there is an error in the string 299 */ convertFromString(double version, String s)300 public Object convertFromString(double version, String s) { 301 if (s == null) 302 return null; 303 304 // Parse the string 305 Enumeration e = ListParser.getListElements(s, 3); 306 String type = null, name = null, attr = null; 307 308 try { 309 type = (String)e.nextElement(); 310 name = (String)e.nextElement(); 311 attr = (String)e.nextElement(); 312 } 313 catch (NoSuchElementException ex) { 314 throw new ParseException(Global.newline() + 315 /* BEGIN JSTYLED */ 316 Global.getMsg("sunsoft.jws.visual.rt.type.AMConverter.________Incomplete__attri.1") + 317 /* END JSTYLED */ 318 Global.newline() + /* NOI18N */" type = " + type + 319 Global.newline() + /* NOI18N */" name = " + name + 320 Global.newline() + /* NOI18N */" attr = " + attr); 321 } 322 323 // Start recording AMRef's made during construction of tree 324 AMRef.startRecording(); 325 326 // Create the attribute manager 327 AttributeManager mgr = convertParent(type, name); 328 if (mgr == null) 329 return null; 330 331 // Parse the attributes and children 332 convertChildren(version, mgr, attr); 333 334 // Stop recording and resolve all AMRef's that were made 335 AMRef.stopRecording(mgr); 336 337 return mgr; 338 } 339 convertParent(String type, String name)340 private AttributeManager convertParent(String type, String name) { 341 AttributeManager mgr = null; 342 343 // Instantiate a new attribute manager 344 Class onLineType = searchShadowPath(type); 345 if (onLineType == null) 346 return null; 347 348 try { 349 mgr = (AttributeManager) onLineType.newInstance(); 350 } 351 catch (IllegalAccessException e) { 352 /* BEGIN JSTYLED */ 353 throw new ParseException(Global.fmtMsg("sunsoft.jws.visual.rt.type.AMConverter.FMT.1", Global.getMsg("sunsoft.jws.visual.rt.type.AMConverter.Could__not__access__"), onLineType.getName())); 354 /* END JSTYLED */ 355 } 356 catch (InstantiationException e) { 357 /* BEGIN JSTYLED */ 358 throw new ParseException(Global.fmtMsg("sunsoft.jws.visual.rt.type.AMConverter.FMT.2", Global.getMsg("sunsoft.jws.visual.rt.type.AMConverter.Could__not__instantiat.2"), onLineType.getName())); 359 /* END JSTYLED */ 360 } 361 362 if (mgr != null) { 363 // Assign name of shadow object 364 mgr.set(/* NOI18N */"name", name); 365 } 366 367 return mgr; 368 } 369 convertChildren(double version, AttributeManager parent, String attr)370 private void convertChildren(double version, 371 AttributeManager parent, String attr) { 372 String type, name; 373 String children = attrlistconv.convertFromString 374 (version, parent, attr); 375 if (children == null) 376 return; 377 378 Enumeration e = ListParser.getListElements(children, 3); 379 380 while (e.hasMoreElements()) { 381 type = null; 382 name = null; 383 attr = null; 384 385 try { 386 type = (String)e.nextElement(); 387 name = (String)e.nextElement(); 388 attr = (String)e.nextElement(); 389 } 390 catch (NoSuchElementException ex) { 391 throw new ParseException(Global.newline() + 392 /* BEGIN JSTYLED */ 393 Global.getMsg("sunsoft.jws.visual.rt.type.AMConverter.________Incomplete__attri.3") + 394 /* END JSTYLED */ 395 Global.newline() + /* NOI18N */" type = " + type + 396 Global.newline() + /* NOI18N */" name = " + name + 397 Global.newline() + /* NOI18N */" attr = " + attr); 398 } 399 400 AttributeManager child = convertParent(type, name); 401 if (child == null) 402 continue; 403 404 // 405 // Insert a frame around any panels that are 406 // immediate children 407 // of the root, and mark the frame as a panel. 408 // 409 if ((parent instanceof Root) && 410 (child instanceof PanelShadow)) { 411 FrameShadow f = new FrameShadow(); 412 f.isPanel(true); 413 414 ((AMContainer)parent).add(f); 415 f.add(child); 416 } else { 417 // REMIND: add error check for non-AMContainer type 418 ((AMContainer)parent).add(child); 419 } 420 421 convertChildren(version, child, attr); 422 } 423 } 424 425 /** 426 * The conversion of shadow trees into code is performed within the 427 * designer and not implemented here. This method should never be 428 * called. 429 * 430 * @exception Error when an attempt is made to call this method 431 */ convertToCode(Object obj)432 public String convertToCode(Object obj) { 433 /* BEGIN JSTYLED */ 434 throw new Error(Global.fmtMsg("sunsoft.jws.visual.rt.type.AMConverter.FMT.3", Global.getMsg("sunsoft.jws.visual.rt.type.AMConverter.will__not__generate__co.4"), 435 Global.getMsg("sunsoft.jws.visual.rt.type.AMConverter.implementation__of__th.5"))); 436 /* END JSTYLED */ 437 } 438 } 439