1 28 29 30 package com.caucho.widget; 31 32 import com.caucho.lifecycle.Lifecycle; 33 import com.caucho.util.L10N; 34 35 import java.io.IOException ; 36 import java.util.AbstractMap ; 37 import java.util.Collections ; 38 import java.util.HashSet ; 39 import java.util.Map ; 40 import java.util.Set ; 41 import java.util.logging.Level ; 42 import java.util.logging.Logger ; 43 44 47 abstract public class Widget<S extends WidgetState> 48 extends AbstractMap <String , Widget> 49 { 50 private static L10N L = new L10N( Widget.class ); 51 52 static protected final Logger log = 53 Logger.getLogger( Widget.class.getName() ); 54 55 private String _id; 56 private String _clientId; 57 private String _parameterName; 58 private String _modeParameterName; 59 private String _preferencePrefix; 60 private String _cssClass; 61 private WidgetPreferences _widgetPreferences; 62 private WidgetMode _widgetMode; 63 private HashSet <WidgetMode> _allowedWidgetModesSet; 64 65 private Widget _parent; 66 67 private Lifecycle _lifecycle = new Lifecycle(); 68 69 private RendererCache _rendererCache = new RendererCache(); 70 71 72 public Widget() 73 { 74 } 75 76 public Widget( String id ) 77 { 78 setId( id ); 79 } 80 81 public Widget( Widget parent ) 82 { 83 setParent( parent ); 84 parent.put( null, this ); 85 } 86 87 public Widget( Widget parent, String id ) 88 { 89 setParent( parent ); 90 setId( id ); 91 parent.put( getId(), this ); 92 } 93 94 public void setParent( Widget parent ) 95 { 96 _parent = parent; 97 } 98 99 public Widget getParent() 100 { 101 return _parent; 102 } 103 104 public void setId( String id ) 105 { 106 _id = id; 107 } 108 109 public String getId() 110 { 111 return _id; 112 } 113 114 protected String calculateId( Widget child ) 115 { 116 return "x" + size(); 117 } 118 119 123 public void setClientId( String clientId ) 124 { 125 _clientId = clientId; 126 } 127 128 public String getClientId() 129 { 130 if ( _clientId == null ) { 131 if ( _parent == null ) 132 _clientId = getId(); 133 else { 134 StringBuffer buf = new StringBuffer (); 135 136 appendId( buf, _parent, '_' ); 137 buf.append( getId() ); 138 139 _clientId = buf.toString(); 140 } 141 } 142 143 return _clientId; 144 } 145 146 private static void appendId( StringBuffer buf, Widget w, char sep ) 147 { 148 if ( w == null ) 149 return; 150 151 if ( w._parent != null ) { 152 appendId( buf, w._parent, sep ); 153 } 154 155 if ( w.getId() != null ) { 156 buf.append( w.getId() ); 157 buf.append( sep ); 158 } 159 } 160 161 165 public void setParameterName( String parameterName ) 166 { 167 _parameterName = parameterName; 168 } 169 170 public String getParameterName() 171 { 172 if ( _parameterName == null ) { 173 if ( _parent == null ) 174 _parameterName = getId(); 175 else { 176 StringBuffer buf = new StringBuffer (); 177 178 appendId( buf, _parent, '.' ); 179 buf.append( getId() ); 180 181 _parameterName = buf.toString(); 182 } 183 } 184 185 return _parameterName; 186 } 187 188 204 public void setCssClass( String cssClass ) 205 { 206 boolean add = cssClass.charAt( 0 ) == '+'; 207 boolean del = cssClass.charAt( 0 ) == '-'; 208 209 if ( add || del ) { 210 cssClass = cssClass.substring(1); 211 String current = getCssClass(); 212 213 StringBuffer cssClassBuf = new StringBuffer (); 214 215 if ( current != null && current.length() > 0 ) { 216 String [] split = current.split( "\\s*" ); 217 218 for ( int i = 0; i < split.length; i++ ) { 219 String token = split[i]; 220 221 if ( token.equals( cssClass ) ) 222 continue; 223 224 cssClassBuf.append( token ); 225 } 226 } 227 228 if ( add ) 229 cssClassBuf.append( cssClass ); 230 231 _cssClass = cssClassBuf.toString(); 232 } 233 else { 234 _cssClass = cssClass; 235 } 236 } 237 238 241 public String getLogId() 242 { 243 StringBuffer buf = new StringBuffer (); 244 245 String classname = getClass().getName(); 246 classname = classname.substring( classname.lastIndexOf('.') + 1); 247 buf.append( classname ); 248 buf.append('['); 249 250 appendLogId( buf, this ); 251 252 if ( _parent == null ) 253 buf.append('/'); 254 255 buf.append(']'); 256 257 return buf.toString(); 258 } 259 260 private static void appendLogId( StringBuffer buf, Widget w ) 261 { 262 if ( w._parent != null ) { 263 appendLogId( buf, w._parent ); 264 buf.append( '/' ); 265 } 266 267 if ( w.getId() != null ) 268 buf.append( w.getId() ); 269 } 270 271 272 276 public String getCssClass() 277 { 278 if ( _cssClass == null ) { 279 StringBuffer buf = new StringBuffer (); 280 281 String shortName = getClass().getName(); 282 283 int i = shortName.lastIndexOf( '.' ) + 1; 284 285 for ( ; i < shortName.length(); i++ ) 286 buf.append( shortName.charAt( i ) ); 287 288 buf.append(' '); 289 buf.append( getId() ); 290 291 _cssClass = buf.toString(); 292 } 293 294 return _cssClass; 295 } 296 297 301 public void setModeParameterName( String modeParameterName ) 302 { 303 _modeParameterName = modeParameterName; 304 } 305 306 public String getModeParameterName() 307 { 308 if ( _modeParameterName == null ) 309 _modeParameterName = "_" + getParameterName() + "_"; 310 311 return _modeParameterName; 312 } 313 314 public WidgetPreferences createWidgetPreferences() 315 { 316 if ( _widgetPreferences == null ) { 317 _widgetPreferences = new WidgetPreferences(); 318 } 319 320 return _widgetPreferences; 321 } 322 323 public void addPreference( WidgetPreference widgetPreference ) 324 { 325 WidgetPreferences widgetPreferences = createWidgetPreferences(); 326 327 widgetPreferences.addPreference( widgetPreference ); 328 } 329 330 336 public void setPreferencePrefix( String preferencePrefix ) 337 { 338 _preferencePrefix = preferencePrefix; 339 } 340 341 344 public String getPreferenceValue( WidgetConnection connection, String key ) 345 { 346 String [] values = getPreferenceValues( connection, key ); 347 348 if ( values == null ) 349 return null; 350 else if ( values.length == 0 ) 351 return ""; 352 else 353 return values[0]; 354 } 355 356 359 public String [] getPreferenceValues( WidgetConnection connection, String key ) 360 { 361 WidgetPreference widgetPreference = getWidgetPreference( key ); 362 363 boolean isReadOnly = widgetPreference != null 364 && !widgetPreference.isReadOnly(); 365 366 String [] values = null; 367 368 if ( widgetPreference != null ) 369 values = widgetPreference.getValues(); 370 371 if ( !isReadOnly ) { 372 key = key + _preferencePrefix; 373 values = connection.getPreferenceValues( key, values ); 374 } 375 376 return values; 377 } 378 379 protected WidgetPreference getWidgetPreference( String key ) 380 { 381 if ( _widgetPreferences == null ) 382 return null; 383 else 384 return _widgetPreferences.get( key ); 385 386 } 387 388 392 public void setWidgetMode( WidgetMode widgetMode ) 393 { 394 _widgetMode = widgetMode; 395 } 396 397 WidgetMode getWidgetMode() 398 { 399 return _widgetMode; 400 } 401 402 405 public void addAllowedWidgetMode( WidgetMode widgetMode ) 406 { 407 if ( _allowedWidgetModesSet == null ) 408 _allowedWidgetModesSet = new HashSet <WidgetMode>(); 409 410 _allowedWidgetModesSet.add( widgetMode ); 411 } 412 413 public boolean isWidgetModeAllowed( WidgetMode widgetMode ) 414 { 415 if ( _allowedWidgetModesSet == null ) 416 return true; 417 else 418 return _allowedWidgetModesSet.contains( widgetMode ); 419 } 420 421 public void init() 422 throws WidgetException 423 { 424 } 425 426 private void initAll() 427 throws WidgetException 428 { 429 if ( !_lifecycle.toInitializing() ) 430 return; 431 432 if ( _id == null && _parent != null ) 433 throw new IllegalStateException ( L.l( "`{0}' is required", "id" ) ); 434 435 if ( _preferencePrefix == null ) 436 _preferencePrefix = _id + "."; 437 438 init(); 439 440 _lifecycle.toActive(); 441 } 442 443 public Set <Map.Entry <String ,Widget>> entrySet() 444 { 445 return (Set <Map.Entry <String ,Widget>>) Collections.EMPTY_SET; 446 } 447 448 public Widget put( String id, Widget value ) 449 { 450 throw new UnsupportedOperationException (); 451 } 452 453 457 protected S decode( WidgetConnection connection ) 458 throws WidgetException 459 { 460 if ( log.isLoggable( Level.FINER ) ) 461 log.finer( L.l( "decode {0}", getLogId() ) ); 462 463 S state = createState( connection ); 464 state.setWidget( this ); 465 466 String parameterName = getParameterName(); 467 468 if ( parameterName == null && getParent() != null ) 469 throw new IllegalStateException ( 470 L.l("`{0}' cannot be null", "parameter-name" ) ); 471 472 if ( parameterName != null ) { 473 String [] data = connection.getParameterValues( getParameterName() ); 474 475 if ( log.isLoggable( Level.FINEST ) ) 476 log.finest( L.l( "data from parameter {0} is {1}", 477 getParameterName(), data ) ); 478 479 state.decode( data ); 480 } 481 482 decodeChildren( connection, state ); 483 484 return state; 485 } 486 487 protected void decodeChildren( WidgetConnection connection, 488 WidgetState state ) 489 throws WidgetException 490 { 491 if ( !isEmpty() ) { 492 for ( Widget child : values() ) { 493 decodeChild( connection, state, child ); 494 } 495 } 496 } 497 498 protected WidgetState decodeChild( WidgetConnection connection, 499 WidgetState thisState, 500 Widget child ) 501 throws WidgetException 502 { 503 WidgetState childState = child.decode( connection ); 504 childState.setParent( thisState ); 505 506 thisState.put( child.getId(), childState ); 507 508 return childState; 509 } 510 511 abstract protected S createState( WidgetConnection connection ) 512 throws WidgetException; 513 514 private void encodeTree( WidgetURL url, 515 WidgetState state, 516 Widget target ) 517 throws WidgetException 518 { 519 encodeTree( url, state, target, false, false ); 520 } 521 522 private void encodeTree( WidgetURL url, 523 WidgetState state, 524 Widget target, 525 boolean isAction, 526 boolean sawTarget ) 527 throws WidgetException 528 { 529 if ( target == this ) { 530 sawTarget = true; 531 isAction = isAction( state ); 532 } 533 534 encode( url, state, isAction ); 535 536 if ( !isEmpty() ) { 537 for ( Widget child : values() ) { 538 WidgetState childState = state.get( child.getId() ); 539 540 if ( childState == null ) { 541 throw new IllegalStateException ( 542 L.l( "no state for `{0}', missing decode()?", 543 child.getLogId() ) ); 544 } 545 546 child.encodeTree( url, childState, target, isAction, sawTarget ); 547 } 548 } 549 } 550 551 protected void encode( WidgetURL url, 552 WidgetState state, 553 boolean isAction ) 554 throws WidgetException 555 { 556 if ( log.isLoggable( Level.FINEST ) ) 557 log.finest( L.l( "encode {0}", getLogId() ) ); 558 559 WidgetMode widgetMode = state._widgetMode; 560 561 if ( widgetMode != null ) { 562 if ( widgetMode == WidgetMode.VIEW 563 || widgetMode.equals( WidgetMode.VIEW ) ) 564 { 565 if ( state.getParent() != null ) 566 url.setParameter( getModeParameterName(), widgetMode.toString() ); 567 } 568 else { 569 url.setParameter( getModeParameterName(), widgetMode.toString() ); 570 } 571 } 572 573 if ( isAction && isActionParameter( state ) ) { 574 url.setAction( true ); 575 } 576 else { 577 String [] data = state.encode(); 578 579 if ( data != null ) 580 url.setParameter( getParameterName(), data ); 581 } 582 } 583 584 594 protected boolean isActionParameter( WidgetState state ) 595 { 596 return false; 597 } 598 599 605 protected boolean isAction( WidgetState state ) 606 { 607 return false; 608 } 609 610 616 protected WidgetURL createURL( WidgetConnection connection ) 617 throws WidgetException 618 { 619 Widget target = this; 620 Widget top = this; 621 622 while ( top.getParent() != null ) 623 top = top.getParent(); 624 625 WidgetURL url = connection.createURL(); 626 WidgetState state = connection.prepare( top ); 627 628 top.encodeTree( url, state, target ); 629 630 return url; 631 } 632 633 public void render( WidgetConnection connection, S widgetState ) 634 throws WidgetException, IOException 635 { 636 if ( ! _lifecycle.isActive() ) 637 initAll(); 638 639 WidgetRenderer<S> widgetRenderer 640 = _rendererCache.getRenderer( connection, this, widgetState ); 641 642 widgetRenderer.render( connection, widgetState ); 643 } 644 645 public void destroy() 646 { 647 if ( !_lifecycle.toDestroying() ) 648 return; 649 650 _lifecycle.toDestroy(); 651 } 652 } 653 | Popular Tags |