public static Logger getLogger() {
   Multivalent.getInstance();
   return Multivalent.getLogger();
 }
  /**
   * Centralized behavior instantiation <i>factory</i>: <b>instantiate all behaviors through this
   * method</b> -- never use <code>new <var>behavior</var>(...)</code>.
   *
   * <ul>
   *   <li>remapping of names so can dynamically replace references in old hubs
   *   <li>centralized, correct instantiation and error handling
   * </ul>
   *
   * {@link #restore(ESISNode, Map, Layer)} is called as part of instantiation, serving the place of
   * arguments to a constructor. Logical names are normalized to all lowercase.
   */
  public static Behavior getInstance(
      String logicalname,
      String behaviorclass,
      ESISNode children,
      Map<String, Object> attr,
      Layer layer) {
    assert logicalname != null
            && behaviorclass != null /*&& (layer!=null || xxx instanceof Layer)--topmost Layer*/
        : "logical=" + logicalname + ", class=" + behaviorclass;
    if (behaviorclass == null) return null; // if not testing (asserts on), keep on truckin'

    if (multivalent.Meta.MONITOR /*false*/ && layer != null && layer.getBrowser() != null) {
      Browser br = layer.getBrowser();
      Graphics g = br.getGraphics(); // -- works, but not well
      if (Behavior.rainbowi_ == Behavior.RAINBOW.length) Behavior.rainbowi_ = 0;
      if (g != null) { // !Multivalent.standalone_ / embedded in Swing
        g.setColor(Behavior.RAINBOW[Behavior.rainbowi_++]);
        g.fillRect(0, 0, 10 /*rainbowi_*/, 10); // g.drawLine(0,10, 10,0);
      }

      /*		g.setColor(Color.WHITE); g.fillRect(250,y_, 600,20);
      g.setColor(Color.BLACK); rfont_.drawString(g, logicalname+" / "+behaviorclass, 300, y_+15);
      y_ += 20; if (y_>20*10) y_ = 0;	// set to 600 to conver page, but can only take in 10 lines at a time
      	 */
    }
    // long start = System.currentTimeMillis();

    // String oname = logicalname;
    logicalname = logicalname.toLowerCase();
    // if (!(oname.equals(logicalname))) System.out.println("uppercase logical: "+oname);	// warn of
    // this inefficiency

    Multivalent v = Multivalent.getInstance();
    String bname = v.remapBehavior(behaviorclass);
    Logger log = getLogger();
    // getLogger().finest((/*"getInstance "+logicalname+"/"+behaviorclass+"=>"+bname);

    if (Behavior.deadbe__.get(bname) == null)
      try {
        ClassLoader cl = /*v.getJARsClassLoader();*/ v.getClass().getClassLoader();
        // assert cl == Behavior.class.getClassLoader();	// true now with new bootstrapping
        Object bc = Class.forName(bname, true, cl).newInstance();
        Behavior be = (Behavior) bc;
        // be.setName(logicalname);	// can't save uppercase
        be.name_ = logicalname;
        // be.name_ = (logicalname!=null? logicalname.toLowerCase(): null);
        be.classname_ = behaviorclass;

        // System.out.println(bname);
        // see save() -- this still ok
        // if (attr==null) {} else if (attr.get(ATTR_BEHAVIOR)!=null) { if (attr.size()==1)
        // attr=null; else attr.remove(ATTR_BEHAVIOR); }

        /*
        long time = System.currentTimeMillis() - start;
        if (false && g!=null/* && time > 0L* /) {
        	g.drawString(Long.toString(time), 250,15);
        	try { Thread.currentThread().sleep(2000L); } catch (Exception e) {}
        }
        		 */
        be.restore(
            children, attr,
            layer); // after added to layer, so can climb around and find things during restore
        // log.finest("created "+bname);

        // assert layer!=null || be instanceof Layer;	// => temporary use of behavior that don't
        // want to make logical part of document
        return be;

      } catch (ClassNotFoundException e) {
        log.warning("couldn't find behavior " + bname + " -- ignored");

      } catch (ClassCastException e) {
        log.severe(
            "class " + bname + " is not a behavior (does not subclass from Behavior) -- ignored");
      } catch (InstantiationException e) {
        log.severe("couldn't instantiate " + bname + " -- is it abstract?");
      } catch (IllegalAccessException e) {
        log.severe(bname + ": " + e + " -- perhaps class or constructor needs to be public");

      } catch (Exception e) {
        e.printStackTrace();
        log.severe("unanticipated error while restoring " + logicalname + "/" + bname + ": " + e);
      }

    // error fall through
    Behavior.deadbe__.put(bname, bname);
    return null;
  }