Package org.beryl.gui

Source Code of org.beryl.gui.WidgetFactory

/*
* Beryl - A web platform based on XML, XSLT and Java
* This file is part of the Beryl XML GUI
*
* Copyright (C) 2004 Wenzel Jakob <wazlaf@tigris.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.

* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-3107  USA
*/

package org.beryl.gui;

import java.awt.Component;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;

import javax.swing.JComponent;
import javax.xml.parsers.DocumentBuilderFactory;

import org.beryl.gui.model.MapDataModel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* The widget factory is required to construct XML GUI interfaces from XML description files
*/
public class WidgetFactory {
  public static final String DEFAULT_PREFIX = "org.beryl.gui.widgets.";
  private static WidgetFactory factoryInstance = new WidgetFactory();
  private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  private PropertyFactory pf = PropertyFactory.getInstance();
  private LayoutFactory lf = LayoutFactory.getInstance();
  private AnchorFactory af = AnchorFactory.getInstance();
  private HashMap constructorCache = null;
  private HashMap documentCache = null;

  private WidgetFactory() {
    constructorCache = new HashMap();
    documentCache = new HashMap();
  }

  public static final WidgetFactory getInstance() {
    return factoryInstance;
  }

  public Widget constructWidget(Class controllerClass, String widgetName) throws GUIException {
    return constructWidget(controllerClass, widgetName, null, null, null);
  }

  public Widget constructWidget(Class controllerClass, String widgetName, GUIEventListener listener)
    throws GUIException {
    return constructWidget(controllerClass, widgetName, listener, null, null);
  }

  public Widget constructWidget(Class controllerClass, String widgetName, GUIEventListener listener, MapDataModel dataModel)
    throws GUIException {
    return constructWidget(controllerClass, widgetName, listener, dataModel, null);
  }

  public Widget constructWidget(
    Class controllerClass,
    String widgetName,
    GUIEventListener listener,
    MapDataModel dataModel,
    Widget parentWidget)
    throws GUIException {
    /* Find GUI description file using the controller class */
    URL url = getClass().getResource("/" + controllerClass.getName().replace('.', '/') + ".xml");
    if (url == null)
      throw new GUIException(
        "Class [" + controllerClass.getName() + "] has no gui description file at [" + url + "]");
    return constructWidget(url, widgetName, listener, dataModel, parentWidget);
  }

  public Widget constructWidget(
    URL url,
    String widgetName,
    GUIEventListener listener,
    MapDataModel dataModel,
    Widget parentWidget)
    throws GUIException {
    Document document = null;
    try {
      document = (Document) documentCache.get(url.toString());
      if (document == null) {
        document = dbf.newDocumentBuilder().parse(url.openStream());
        documentCache.put(url.toString(), document);
      }
    } catch (Exception e) {
      throw new GUIException("Could not parse widget file", e);
    }

    return constructWidget(document, widgetName, listener, dataModel, parentWidget);
  }

  private Widget constructWidget(
    Document document,
    String widgetName,
    GUIEventListener listener,
    MapDataModel dataModel,
    Widget parentWidget)
    throws GUIException {

    Element root = document.getDocumentElement();
    String version = root.getAttribute("version");
    NodeList widgets = root.getChildNodes();

    if (!version.equals("1.0")) {
      throw new GUIException("Invalid XML description file version [" + version + "]");
    }

    for (int i = 0; i < widgets.getLength(); i++) {
      Node node = widgets.item(i);
      if (node.getNodeType() == Node.ELEMENT_NODE
        && node.getNodeName().equals("widget")
        && ((Element) node).getAttribute("name").equals(widgetName))
        return constructWidget(document, (Element) node, listener, dataModel, parentWidget);
    }
    throw new GUIException("Widget [" + widgetName + "] could not be found");
  }

  private Widget constructWidget(
    Document descriptionFile,
    Element widgetNode,
    GUIEventListener listener,
    MapDataModel dataModel,
    Widget parentWidget)
    throws GUIException {
    Widget widget = null;
    String widgetClass = widgetNode.getAttribute("class");
    String widgetName = widgetNode.getAttribute("name");
    String widgetPreset = widgetNode.getAttribute("preset");
    boolean hasPreset = !widgetPreset.equals("");
    Constructor widgetConstructor = (Constructor) constructorCache.get(widgetClass + (hasPreset ? "_P" : ""));
    NodeList childNodes = widgetNode.getChildNodes();

    try {
      try {
        if (widgetConstructor == null) {
          String classAttribute = widgetNode.getAttribute("class");
          String className = DEFAULT_PREFIX + classAttribute;
          if (classAttribute.indexOf('.') != -1)
            className = classAttribute;
 
          Class wClass = Class.forName(className);
          if (hasPreset)
            widgetConstructor = wClass.getConstructor(new Class[] { Widget.class, String.class, String.class });
          else
            widgetConstructor = wClass.getConstructor(new Class[] { Widget.class, String.class });
          constructorCache.put(widgetClass + (hasPreset ? "_P" : ""), widgetConstructor);
        }
        if (hasPreset)
          widget =
            (Widget) widgetConstructor.newInstance(
              new Object[] { parentWidget, widgetName.equals("") ? null : widgetName, widgetPreset });
        else
          widget =
            (Widget) widgetConstructor.newInstance(
              new Object[] { parentWidget, widgetName.equals("") ? null : widgetName });
      } catch (ClassNotFoundException e) {
        throw new GUIException("Unknown widget class [" + widgetNode.getAttribute("class") + "]");
      } catch (NoSuchMethodException e) {
        throw new GUIException("Widget constructor not found", e);
      } catch (IllegalAccessException e) {
        throw new GUIException("Widget constructor could not be called", e);
      } catch (InstantiationException e) {
        throw new GUIException("Widget is abstract", e);
      } catch (InvocationTargetException e) {
        throw new GUIException("Widget constructor threw an exception", e);
      }

      for (int i = 0; i < childNodes.getLength(); i++) {
        if (childNodes.item(i).getNodeName().equals("property")) {
          Element propertyNode = (Element) childNodes.item(i);
          widget.setProperty(propertyNode.getAttribute("name"), pf.constructProperty(propertyNode));
        } else if (listener != null && childNodes.item(i).getNodeName().equals("emit")) {
          Element emitNode = (Element) childNodes.item(i);
          widget.addListener(emitNode.getAttribute("event"), emitNode.getAttribute("name"), listener);
        } else if (childNodes.item(i).getNodeName().equals("layout")) {
          Element layoutNode = (Element) childNodes.item(i);
          widget.setProperty("layout", lf.constructLayout(widget, layoutNode));
        }
      }
    } catch (Exception e) {
      throw new GUIException("Error while creating a widget of class [" + widgetClass + "], name [" + widgetName + "] and preset [" + widgetPreset + "]", e);
    }
    /* Process child nodes after all properties are set */
    for (int i = 0; i < childNodes.getLength(); i++) {
      if (childNodes.item(i).getNodeName().equals("widget")) {
        Element childNode = (Element) childNodes.item(i);
        Widget childWidget = null;
        Object anchor = null;

        /* Get the child's anchor subnode */
        Element anchorNode = XMLUtils.getChild(childNode, "anchor");

        /* Include other files if required */
        if (!childNode.getAttribute("include").equals("")) {
          String includeName = childNode.getAttribute("name");
          String includeFile = childNode.getAttribute("include");
          if (includeName.equals(""))
            throw new GUIException("The name attribute needs to be specified for includes");
          if (!includeFile.equals("this")) {
            URL url = getClass().getResource("/" + includeFile);
            if (url == null)
              throw new GUIException("Include file [" + includeFile + "] does not exist");
            childWidget = constructWidget(url, includeName, listener, dataModel, widget);
          } else {
            childWidget = constructWidget(descriptionFile, includeName, listener, dataModel, widget);
          }
          if (childWidget == null)
            throw new GUIException(
              "Widget [" + includeName + "] not found in include file [" + includeFile + "]");
        } else {
          childWidget = constructWidget(descriptionFile, childNode, listener, dataModel, widget);
        }
        if (anchorNode != null) {
          anchor = af.constructAnchor(anchorNode);
          if (anchor instanceof AnchorFactory.BoxAnchor) {
            AnchorFactory.BoxAnchor ba = (AnchorFactory.BoxAnchor) anchor;
            JComponent component = (JComponent) childWidget.getWidget();
            component.setAlignmentX(ba.getAlignmentX());
            component.setAlignmentY(ba.getAlignmentY());
            anchor = null;
          }
        } else {
          Component comp = (Component) childWidget.getWidget();

          if (comp != null && comp instanceof JComponent) {
            JComponent component = (JComponent) comp;

            component.setAlignmentX(0.0f);
            component.setAlignmentY(0.0f);
          }
        }
        widget.addChild(childWidget, anchor);
      }
    }
    try {
      /* Set the data model */
      if (dataModel != null)
        widget.setDataModel(dataModel);

      /* Finalize construction */
      widget.finalizeConstruction();
    } catch (Exception e) {
      throw new GUIException("Error while finalizing a widget of class [" + widgetClass + "], name [" + widgetName + "] and preset [" + widgetPreset + "]", e);
    }

    return widget;
  }
}
TOP

Related Classes of org.beryl.gui.WidgetFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.