Clover coverage report - Code Coverage for tapestry release 4.0-beta-8
Coverage timestamp: Sat Sep 24 2005 11:50:34 EDT
file stats: LOC: 769   Methods: 27
NCLOC: 288   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Tapestry.java 60.5% 52.8% 63% 56.1%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.tapestry;
 16   
 17    import java.io.IOException;
 18    import java.io.InputStream;
 19    import java.text.MessageFormat;
 20    import java.util.ArrayList;
 21    import java.util.Collection;
 22    import java.util.HashMap;
 23    import java.util.Iterator;
 24    import java.util.List;
 25    import java.util.Locale;
 26    import java.util.Map;
 27    import java.util.Properties;
 28    import java.util.ResourceBundle;
 29    import java.util.Set;
 30   
 31    import org.apache.hivemind.ApplicationRuntimeException;
 32    import org.apache.hivemind.HiveMind;
 33    import org.apache.hivemind.Location;
 34    import org.apache.hivemind.service.ClassFabUtils;
 35    import org.apache.tapestry.event.ChangeObserver;
 36    import org.apache.tapestry.event.ObservedChangeEvent;
 37    import org.apache.tapestry.services.ServiceConstants;
 38    import org.apache.tapestry.spec.IComponentSpecification;
 39    import org.apache.tapestry.util.StringSplitter;
 40   
 41    /**
 42    * A placeholder for a number of (static) methods that don't belong elsewhere, as well as a global
 43    * location for static constants.
 44    *
 45    * @since 1.0.1
 46    * @author Howard Lewis Ship
 47    */
 48   
 49    public final class Tapestry
 50    {
 51    /**
 52    * The name ("action") of a service that allows behavior to be associated with an
 53    * {@link IAction} component, such as {@link org.apache.tapestry.link.ActionLink }or
 54    * {@link org.apache.tapestry.form.Form}.
 55    * <p>
 56    * This service is used with actions that are tied to the dynamic state of the page, and which
 57    * require a rewind of the page.
 58    */
 59   
 60    public final static String ACTION_SERVICE = "action";
 61   
 62    /**
 63    * The name ("direct") of a service that allows stateless behavior for an {@link
 64    * org.apache.tapestry.link.DirectLink} component.
 65    * <p>
 66    * This service rolls back the state of the page but doesn't rewind the the dynamic state of the
 67    * page the was the action service does, which is more efficient but less powerful.
 68    * <p>
 69    * An array of String parameters may be included with the service URL; these will be made
 70    * available to the {@link org.apache.tapestry.link.DirectLink} component's listener.
 71    */
 72   
 73    public final static String DIRECT_SERVICE = "direct";
 74   
 75    /**
 76    * The name ("external") of a service that a allows {@link IExternalPage} to be selected.
 77    * Associated with a {@link org.apache.tapestry.link.ExternalLink} component.
 78    * <p>
 79    * This service enables {@link IExternalPage}s to be accessed via a URL. External pages may be
 80    * booked marked using their URL for future reference.
 81    * <p>
 82    * An array of Object parameters may be included with the service URL; these will be passed to
 83    * the {@link IExternalPage#activateExternalPage(Object[], IRequestCycle)} method.
 84    */
 85   
 86    public final static String EXTERNAL_SERVICE = "external";
 87   
 88    /**
 89    * The name ("page") of a service that allows a new page to be selected. Associated with a
 90    * {@link org.apache.tapestry.link.PageLink} component.
 91    * <p>
 92    * The service requires a single parameter: the name of the target page.
 93    */
 94   
 95    public final static String PAGE_SERVICE = "page";
 96   
 97    /**
 98    * The name ("home") of a service that jumps to the home page. A stand-in for when no service is
 99    * provided, which is typically the entrypoint to the application.
 100    */
 101   
 102    public final static String HOME_SERVICE = "home";
 103   
 104    /**
 105    * The name ("restart") of a service that invalidates the session and restarts the application.
 106    * Typically used just to recover from an exception.
 107    */
 108   
 109    public static final String RESTART_SERVICE = "restart";
 110   
 111    /**
 112    * The name ("asset") of a service used to access internal assets.
 113    */
 114   
 115    public static final String ASSET_SERVICE = "asset";
 116   
 117    /**
 118    * The name ("reset") of a service used to clear cached template and specification data and
 119    * remove all pooled pages. This is only used when debugging as a quick way to clear the out
 120    * cached data, to allow updated versions of specifications and templates to be loaded (without
 121    * stopping and restarting the servlet container).
 122    * <p>
 123    * This service is only available if the Java system property
 124    * <code>org.apache.tapestry.enable-reset-service</code> is set to <code>true</code>.
 125    */
 126   
 127    public static final String RESET_SERVICE = "reset";
 128   
 129    /**
 130    * Query parameter that identfies the service for the request.
 131    *
 132    * @since 1.0.3
 133    * @deprecated To be removed in 4.1. Use
 134    * {@link org.apache.tapestry.services.ServiceConstants#SERVICE} instead.
 135    */
 136   
 137    public static final String SERVICE_QUERY_PARAMETER_NAME = ServiceConstants.SERVICE;
 138   
 139    /**
 140    * The query parameter for application specific parameters to the service (this is used with the
 141    * direct service). Each of these values is encoded with
 142    * {@link java.net.URLEncoder#encode(String)} before being added to the URL. Multiple values are
 143    * handle by repeatedly establishing key/value pairs (this is a change from behavior in 2.1 and
 144    * earlier).
 145    *
 146    * @since 1.0.3
 147    * @deprecated To be removed in 4.1. Use
 148    * {@link org.apache.tapestry.services.ServiceConstants#PARAMETER} instead.
 149    */
 150   
 151    public static final String PARAMETERS_QUERY_PARAMETER_NAME = ServiceConstants.PARAMETER;
 152   
 153    /**
 154    * Property name used to get the extension used for templates. This may be set in the page or
 155    * component specification, or in the page (or component's) immediate container (library or
 156    * application specification). Unlike most properties, value isn't inherited all the way up the
 157    * chain. The default template extension is "html".
 158    *
 159    * @since 3.0
 160    */
 161   
 162    public static final String TEMPLATE_EXTENSION_PROPERTY = "org.apache.tapestry.template-extension";
 163   
 164    /**
 165    * The name of an {@link org.apache.tapestry.IRequestCycle} attribute in which the currently
 166    * rendering {@link org.apache.tapestry.components.ILinkComponent} is stored. Link components do
 167    * not nest.
 168    */
 169   
 170    public static final String LINK_COMPONENT_ATTRIBUTE_NAME = "org.apache.tapestry.active-link-component";
 171   
 172    /**
 173    * Suffix appended to a parameter name to form the name of a property that stores the binding
 174    * for the parameter.
 175    *
 176    * @since 3.0
 177    */
 178   
 179    public static final String PARAMETER_PROPERTY_NAME_SUFFIX = "Binding";
 180   
 181    /**
 182    * Key used to obtain an extension from the application specification. The extension, if it
 183    * exists, implements {@link org.apache.tapestry.request.IRequestDecoder}.
 184    *
 185    * @since 2.2
 186    */
 187   
 188    public static final String REQUEST_DECODER_EXTENSION_NAME = "org.apache.tapestry.request-decoder";
 189   
 190    /**
 191    * Name of optional application extension for the multipart decoder used by the application. The
 192    * extension must implement {@link org.apache.tapestry.multipart.IMultipartDecoder} (and is
 193    * generally a configured instance of
 194    * {@link org.apache.tapestry.multipart.DefaultMultipartDecoder}).
 195    *
 196    * @since 3.0
 197    */
 198   
 199    public static final String MULTIPART_DECODER_EXTENSION_NAME = "org.apache.tapestry.multipart-decoder";
 200   
 201    /**
 202    * Method id used to check that {@link IPage#validate(IRequestCycle)} is invoked.
 203    *
 204    * @see #checkMethodInvocation(Object, String, Object)
 205    * @since 3.0
 206    */
 207   
 208    public static final String ABSTRACTPAGE_VALIDATE_METHOD_ID = "AbstractPage.validate()";
 209   
 210    /**
 211    * Method id used to check that {@link IPage#detach()} is invoked.
 212    *
 213    * @see #checkMethodInvocation(Object, String, Object)
 214    * @since 3.0
 215    */
 216   
 217    public static final String ABSTRACTPAGE_DETACH_METHOD_ID = "AbstractPage.detach()";
 218   
 219    /**
 220    * Regular expression defining a simple property name. Used by several different parsers. Simple
 221    * property names match Java variable names; a leading letter (or underscore), followed by
 222    * letters, numbers and underscores.
 223    *
 224    * @since 3.0
 225    */
 226   
 227    public static final String SIMPLE_PROPERTY_NAME_PATTERN = "^_?[a-zA-Z]\\w*$";
 228   
 229    /**
 230    * Name of an application extension used as a factory for
 231    * {@link org.apache.tapestry.engine.IMonitor}instances. The extension must implement
 232    * {@link org.apache.tapestry.engine.IMonitorFactory}.
 233    *
 234    * @since 3.0
 235    */
 236   
 237    public static final String MONITOR_FACTORY_EXTENSION_NAME = "org.apache.tapestry.monitor-factory";
 238   
 239    /**
 240    * Class name of an {@link ognl.TypeConverter}implementing class to use as a type converter for
 241    * {@link org.apache.tapestry.binding.ExpressionBinding}
 242    */
 243    public static final String OGNL_TYPE_CONVERTER = "org.apache.tapestry.ognl-type-converter";
 244   
 245    /**
 246    * Prevent instantiation.
 247    */
 248   
 249  0 private Tapestry()
 250    {
 251    }
 252   
 253    /**
 254    * The version of the framework; this is updated for major releases.
 255    */
 256   
 257    public static final String VERSION = readVersion();
 258   
 259    /**
 260    * Contains strings loaded from TapestryStrings.properties.
 261    *
 262    * @since 1.0.8
 263    */
 264   
 265    private static ResourceBundle _strings;
 266   
 267    /**
 268    * A {@link Map}that links Locale names (as in {@link Locale#toString()}to {@link Locale}
 269    * instances. This prevents needless duplication of Locales.
 270    */
 271   
 272    private static final Map _localeMap = new HashMap();
 273   
 274    static
 275    {
 276  1 Locale[] locales = Locale.getAvailableLocales();
 277  1 for (int i = 0; i < locales.length; i++)
 278    {
 279  132 _localeMap.put(locales[i].toString(), locales[i]);
 280    }
 281    }
 282   
 283    /**
 284    * Used for tracking if a particular super-class method has been invoked.
 285    */
 286   
 287    private static final ThreadLocal _invokedMethodIds = new ThreadLocal();
 288   
 289    /**
 290    * Copys all informal {@link IBinding bindings}from a source component to the destination
 291    * component. Informal bindings are bindings for informal parameters. This will overwrite
 292    * parameters (formal or informal) in the destination component if there is a naming conflict.
 293    */
 294   
 295  0 public static void copyInformalBindings(IComponent source, IComponent destination)
 296    {
 297  0 Collection names = source.getBindingNames();
 298   
 299  0 if (names == null)
 300  0 return;
 301   
 302  0 IComponentSpecification specification = source.getSpecification();
 303  0 Iterator i = names.iterator();
 304   
 305  0 while (i.hasNext())
 306    {
 307  0 String name = (String) i.next();
 308   
 309    // If not a formal parameter, then copy it over.
 310   
 311  0 if (specification.getParameter(name) == null)
 312    {
 313  0 IBinding binding = source.getBinding(name);
 314   
 315  0 destination.setBinding(name, binding);
 316    }
 317    }
 318    }
 319   
 320    /**
 321    * Gets the {@link Locale}for the given string, which is the result of
 322    * {@link Locale#toString()}. If no such locale is already registered, a new instance is
 323    * created, registered and returned.
 324    */
 325   
 326  0 public static Locale getLocale(String s)
 327    {
 328  0 Locale result = null;
 329   
 330  0 synchronized (_localeMap)
 331    {
 332  0 result = (Locale) _localeMap.get(s);
 333    }
 334   
 335  0 if (result == null)
 336    {
 337  0 StringSplitter splitter = new StringSplitter('_');
 338  0 String[] terms = splitter.splitToArray(s);
 339   
 340  0 switch (terms.length)
 341    {
 342  0 case 1:
 343   
 344  0 result = new Locale(terms[0], "");
 345  0 break;
 346   
 347  0 case 2:
 348   
 349  0 result = new Locale(terms[0], terms[1]);
 350  0 break;
 351   
 352  0 case 3:
 353   
 354  0 result = new Locale(terms[0], terms[1], terms[2]);
 355  0 break;
 356   
 357  0 default:
 358   
 359  0 throw new IllegalArgumentException("Unable to convert '" + s + "' to a Locale.");
 360    }
 361   
 362  0 synchronized (_localeMap)
 363    {
 364  0 _localeMap.put(s, result);
 365    }
 366   
 367    }
 368   
 369  0 return result;
 370   
 371    }
 372   
 373    /**
 374    * Closes the stream (if not null), ignoring any {@link IOException}thrown.
 375    *
 376    * @since 1.0.2
 377    */
 378   
 379  162 public static void close(InputStream stream)
 380    {
 381  162 if (stream != null)
 382    {
 383  162 try
 384    {
 385  162 stream.close();
 386    }
 387    catch (IOException ex)
 388    {
 389    // Ignore.
 390    }
 391    }
 392    }
 393   
 394    /**
 395    * Gets a string from the TapestryStrings resource bundle. The string in the bundle is treated
 396    * as a pattern for {@link MessageFormat#format(java.lang.String, java.lang.Object[])}.
 397    *
 398    * @since 1.0.8
 399    */
 400   
 401  30 public static String format(String key, Object[] args)
 402    {
 403  30 if (_strings == null)
 404  1 _strings = ResourceBundle.getBundle("org.apache.tapestry.TapestryStrings");
 405   
 406  30 String pattern = _strings.getString(key);
 407   
 408  30 if (args == null)
 409  12 return pattern;
 410   
 411  18 return MessageFormat.format(pattern, args);
 412    }
 413   
 414    /**
 415    * Convienience method for invoking {@link #format(String, Object[])}.
 416    *
 417    * @since 3.0
 418    */
 419   
 420  12 public static String getMessage(String key)
 421    {
 422  12 return format(key, null);
 423    }
 424   
 425    /**
 426    * Convienience method for invoking {@link #format(String, Object[])}.
 427    *
 428    * @since 3.0
 429    */
 430   
 431  5 public static String format(String key, Object arg)
 432    {
 433  5 return format(key, new Object[]
 434    { arg });
 435    }
 436   
 437    /**
 438    * Convienience method for invoking {@link #format(String, Object[])}.
 439    *
 440    * @since 3.0
 441    */
 442   
 443  10 public static String format(String key, Object arg1, Object arg2)
 444    {
 445  10 return format(key, new Object[]
 446    { arg1, arg2 });
 447    }
 448   
 449    /**
 450    * Convienience method for invoking {@link #format(String, Object[])}.
 451    *
 452    * @since 3.0
 453    */
 454   
 455  3 public static String format(String key, Object arg1, Object arg2, Object arg3)
 456    {
 457  3 return format(key, new Object[]
 458    { arg1, arg2, arg3 });
 459    }
 460   
 461    private static final String UNKNOWN_VERSION = "Unknown";
 462   
 463    /**
 464    * Invoked when the class is initialized to read the current version file.
 465    */
 466   
 467  1 private static final String readVersion()
 468    {
 469  1 Properties props = new Properties();
 470   
 471  1 try
 472    {
 473  1 InputStream in = Tapestry.class.getResourceAsStream("version.properties");
 474   
 475  1 if (in == null)
 476  0 return UNKNOWN_VERSION;
 477   
 478  1 props.load(in);
 479   
 480  1 in.close();
 481   
 482  1 return props.getProperty("project.version", UNKNOWN_VERSION);
 483    }
 484    catch (IOException ex)
 485    {
 486  0 return UNKNOWN_VERSION;
 487    }
 488   
 489    }
 490   
 491    /**
 492    * Returns the size of a collection, or zero if the collection is null.
 493    *
 494    * @since 2.2
 495    */
 496   
 497  2258 public static int size(Collection c)
 498    {
 499  2258 if (c == null)
 500  1 return 0;
 501   
 502  2257 return c.size();
 503    }
 504   
 505    /**
 506    * Returns the length of the array, or 0 if the array is null.
 507    *
 508    * @since 2.2
 509    */
 510   
 511  289 public static int size(Object[] array)
 512    {
 513  289 if (array == null)
 514  60 return 0;
 515   
 516  229 return array.length;
 517    }
 518   
 519    /**
 520    * Returns true if the Map is null or empty.
 521    *
 522    * @since 3.0
 523    */
 524   
 525  0 public static boolean isEmpty(Map map)
 526    {
 527  0 return map == null || map.isEmpty();
 528    }
 529   
 530    /**
 531    * Returns true if the Collection is null or empty.
 532    *
 533    * @since 3.0
 534    */
 535   
 536  77 public static boolean isEmpty(Collection c)
 537    {
 538  77 return c == null || c.isEmpty();
 539    }
 540   
 541    /**
 542    * Converts a {@link Map} to an even-sized array of key/value pairs. This may be useful when
 543    * using a Map as service parameters (with {@link org.apache.tapestry.link.DirectLink}.
 544    * Assuming the keys and values are simple objects (String, Boolean, Integer, etc.), then the
 545    * representation as an array will encode more efficiently (via
 546    * {@link org.apache.tapestry.util.io.DataSqueezerImpl} than serializing the Map and its
 547    * contents.
 548    *
 549    * @return the array of keys and values, or null if the input Map is null or empty
 550    * @since 2.2
 551    */
 552   
 553  0 public static Object[] convertMapToArray(Map map)
 554    {
 555  0 if (isEmpty(map))
 556  0 return null;
 557   
 558  0 Set entries = map.entrySet();
 559   
 560  0 Object[] result = new Object[2 * entries.size()];
 561  0 int x = 0;
 562   
 563  0 Iterator i = entries.iterator();
 564  0 while (i.hasNext())
 565    {
 566  0 Map.Entry entry = (Map.Entry) i.next();
 567   
 568  0 result[x++] = entry.getKey();
 569  0 result[x++] = entry.getValue();
 570    }
 571   
 572  0 return result;
 573    }
 574   
 575    /**
 576    * Converts an even-sized array of objects back into a {@link Map}.
 577    *
 578    * @see #convertMapToArray(Map)
 579    * @return a Map, or null if the array is null or empty
 580    * @since 2.2
 581    */
 582   
 583  130 public static Map convertArrayToMap(Object[] array)
 584    {
 585  130 if (array == null || array.length == 0)
 586  27 return null;
 587   
 588  103 if (array.length % 2 != 0)
 589  0 throw new IllegalArgumentException(getMessage("Tapestry.even-sized-array"));
 590   
 591  103 Map result = new HashMap();
 592   
 593  103 int x = 0;
 594  103 while (x < array.length)
 595    {
 596  232 Object key = array[x++];
 597  232 Object value = array[x++];
 598   
 599  232 result.put(key, value);
 600    }
 601   
 602  103 return result;
 603    }
 604   
 605    /**
 606    * Given a Class, creates a presentable name for the class, even if the class is a scalar type
 607    * or Array type.
 608    *
 609    * @since 3.0
 610    * @deprecated To be removed in 4.1.
 611    */
 612   
 613  6 public static String getClassName(Class subject)
 614    {
 615  6 return ClassFabUtils.getJavaClassName(subject);
 616    }
 617   
 618    /**
 619    * Creates an exception indicating the binding value is null.
 620    *
 621    * @since 3.0
 622    */
 623   
 624  0 public static BindingException createNullBindingException(IBinding binding)
 625    {
 626  0 return new BindingException(getMessage("null-value-for-binding"), binding);
 627    }
 628   
 629    /** @since 3.0 * */
 630   
 631  0 public static ApplicationRuntimeException createNoSuchComponentException(IComponent component,
 632    String id, Location location)
 633    {
 634  0 return new ApplicationRuntimeException(format("no-such-component", component
 635    .getExtendedId(), id), component, location, null);
 636    }
 637   
 638    /** @since 3.0 * */
 639   
 640  3 public static BindingException createRequiredParameterException(IComponent component,
 641    String parameterName)
 642    {
 643  3 return new BindingException(format("required-parameter", parameterName, component
 644    .getExtendedId()), component, null, component.getBinding(parameterName), null);
 645    }
 646   
 647    /** @since 3.0 * */
 648   
 649  0 public static ApplicationRuntimeException createRenderOnlyPropertyException(
 650    IComponent component, String propertyName)
 651    {
 652  0 return new ApplicationRuntimeException(format(
 653    "render-only-property",
 654    propertyName,
 655    component.getExtendedId()), component, null, null);
 656    }
 657   
 658    /**
 659    * Clears the list of method invocations.
 660    *
 661    * @see #checkMethodInvocation(Object, String, Object)
 662    * @since 3.0
 663    */
 664   
 665  378 public static void clearMethodInvocations()
 666    {
 667  378 _invokedMethodIds.set(null);
 668    }
 669   
 670    /**
 671    * Adds a method invocation to the list of invocations. This is done in a super-class
 672    * implementations.
 673    *
 674    * @see #checkMethodInvocation(Object, String, Object)
 675    * @since 3.0
 676    */
 677   
 678  384 public static void addMethodInvocation(Object methodId)
 679    {
 680  384 List methodIds = (List) _invokedMethodIds.get();
 681   
 682  384 if (methodIds == null)
 683    {
 684  378 methodIds = new ArrayList();
 685  378 _invokedMethodIds.set(methodIds);
 686    }
 687   
 688  384 methodIds.add(methodId);
 689    }
 690   
 691    /**
 692    * Checks to see if a particular method has been invoked. The method is identified by a methodId
 693    * (usually a String). The methodName and object are used to create an error message.
 694    * <p>
 695    * The caller should invoke {@link #clearMethodInvocations()}, then invoke a method on the
 696    * object. The super-class implementation should invoke {@link #addMethodInvocation(Object)} to
 697    * indicate that it was, in fact, invoked. The caller then invokes this method to validate that
 698    * the super-class implementation was invoked.
 699    * <p>
 700    * The list of method invocations is stored in a {@link ThreadLocal} variable.
 701    *
 702    * @since 3.0
 703    */
 704   
 705  374 public static void checkMethodInvocation(Object methodId, String methodName, Object object)
 706    {
 707  374 List methodIds = (List) _invokedMethodIds.get();
 708   
 709  374 if (methodIds != null && methodIds.contains(methodId))
 710  373 return;
 711   
 712  1 throw new ApplicationRuntimeException(Tapestry.format(
 713    "Tapestry.missing-method-invocation",
 714    object.getClass().getName(),
 715    methodName));
 716    }
 717   
 718    /**
 719    * Method used by pages and components to send notifications about property changes.
 720    *
 721    * @param component
 722    * the component containing the property
 723    * @param propertyName
 724    * the name of the property which changed
 725    * @param newValue
 726    * the new value for the property
 727    * @since 3.0
 728    */
 729  31 public static void fireObservedChange(IComponent component, String propertyName, Object newValue)
 730    {
 731  31 ChangeObserver observer = component.getPage().getChangeObserver();
 732   
 733  31 if (observer == null)
 734  11 return;
 735   
 736  20 ObservedChangeEvent event = new ObservedChangeEvent(component, propertyName, newValue);
 737   
 738  20 observer.observeChange(event);
 739    }
 740   
 741    /**
 742    * Returns true if the input is null or contains only whitespace.
 743    * <p>
 744    * Note: Yes, you'd think we'd use <code>StringUtils</code>, but with the change in names and
 745    * behavior between releases, it is smarter to just implement our own little method!
 746    *
 747    * @since 3.0
 748    * @deprecated To be removed in Tapestry 4.1. Use {@link HiveMind#isBlank(java.lang.String)}
 749    * instead.
 750    */
 751   
 752  0 public static boolean isBlank(String input)
 753    {
 754  0 return HiveMind.isBlank(input);
 755    }
 756   
 757    /**
 758    * Returns true if the input is not null and not empty (or only whitespace).
 759    *
 760    * @since 3.0
 761    * @deprecated To be removed in Tapestry 4.1. Use {@link HiveMind#isNonBlank(java.lang.String)}
 762    * instead.
 763    */
 764   
 765  0 public static boolean isNonBlank(String input)
 766    {
 767  0 return HiveMind.isNonBlank(input);
 768    }
 769    }