/*
* Copyright 2004-2005 Revolution Systems Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.revolsys.ui.web.config;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import org.apache.log4j.Logger;
import com.revolsys.record.io.format.xml.StaxReader;
import com.revolsys.record.io.format.xml.XmlProcessor;
import com.revolsys.record.io.format.xml.XmlProcessorContext;
import com.revolsys.ui.html.view.Script;
import com.revolsys.ui.html.view.Style;
import com.revolsys.ui.web.exception.PageNotFoundException;
public class IafConfigXmlProcessor extends XmlProcessor {
private static final Logger log = Logger.getLogger(IafConfigXmlProcessor.class);
private static final Map standardTypes = new HashMap();
static {
standardTypes.put("int", Integer.class);
standardTypes.put("long", Long.class);
standardTypes.put("boolean", Boolean.class);
standardTypes.put("string", String.class);
}
private boolean child = false;
private Config config;
private final LinkedList pageStack = new LinkedList();
private final ServletContext servletContext;
public IafConfigXmlProcessor(final IafConfigXmlProcessor parent) {
super("urn:x-revolsys-com:iaf:core:config");
final XmlProcessorContext context = parent.getContext();
setContext(context);
this.servletContext = parent.servletContext;
this.config = parent.config;
this.child = true;
}
public IafConfigXmlProcessor(final XmlProcessorContext processorContext) {
super("urn:x-revolsys-com:iaf:core:config");
setContext(processorContext);
this.servletContext = (ServletContext)processorContext
.getAttribute("javax.servlet.ServletContext");
}
private boolean getBooleanAttribute(final StaxReader parser, final String name) {
final String value = parser.getAttributeValue(null, name);
if (value != null && (value.equals("yes") || value.equals("true"))) {
return true;
}
return false;
}
private Page getCurrentPage() {
if (this.pageStack.isEmpty()) {
return null;
} else {
return (Page)this.pageStack.getLast();
}
}
private Page getPageByRef(final StaxReader parser, final String pageRef) {
Page page = null;
if (!pageRef.equals("")) {
try {
Page currentPage = getCurrentPage();
while (currentPage != null) {
page = currentPage.getPage(pageRef);
if (page != null) {
currentPage = null;
} else {
currentPage = currentPage.getParent();
}
}
if (page == null) {
page = this.config.getPage(this.config.getBasePath() + pageRef);
}
return page;
} catch (final PageNotFoundException e) {
getContext().addError(e.getMessage(), e, parser.getLocation());
}
}
return page;
}
public ActionConfig processAction(final StaxReader parser)
throws XMLStreamException, IOException {
final String type = parser.getAttributeValue(null, "type");
final String file = parser.getAttributeValue(null, "file");
final ActionConfig action = new ActionConfig(this.config, type);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof Parameter) {
action.addParameter((Parameter)object);
}
}
return action;
}
public Area processArea(final StaxReader parser) throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String component = parser.getAttributeValue(null, "component");
final Area area = new Area(name, component);
parser.skipSubTree();
return area;
}
public Argument processArgument(final StaxReader parser) throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String typePath = parser.getAttributeValue(null, "type");
final String defaultValue = parser.getAttributeValue(null, "default");
Class type = null;
if (typePath != null) {
type = (Class)standardTypes.get(typePath);
if (type == null) {
try {
type = Class.forName(typePath);
} catch (final ClassNotFoundException e) {
log.error(e);
throw new RuntimeException("Type " + typePath + "could not be found", e);
}
}
}
final boolean required = getBooleanAttribute(parser, "required");
final boolean inheritable = getBooleanAttribute(parser, "inheritable");
final Argument argument = new Argument(name, type, defaultValue, required, inheritable);
parser.skipSubTree();
return argument;
}
public Attribute processAttribute(final StaxReader parser)
throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String typePath = parser.getAttributeValue(null, "type");
final String value = parser.getAttributeValue(null, "value");
Class type = null;
if (typePath != null) {
type = (Class)standardTypes.get(typePath);
if (type == null) {
try {
type = Class.forName(typePath);
} catch (final ClassNotFoundException e) {
log.error(e);
throw new RuntimeException("Type " + typePath + "could not be found", e);
}
}
}
final String loaderName = parser.getAttributeValue(null, "loader");
Class loader = null;
if (loaderName != null) {
try {
loader = Class.forName(loaderName);
} catch (final ClassNotFoundException e) {
throw new RuntimeException("Loader " + loaderName + "could not be found", e);
}
}
final String inheritableAttr = parser.getAttributeValue(null, "inheritable");
boolean inheritable = false;
if (inheritableAttr != null
&& (inheritableAttr.equals("yes") || inheritableAttr.equals("true"))) {
inheritable = true;
}
final Attribute attribute = new Attribute(this.config, name, type, value, inheritable, loader);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof Parameter) {
attribute.addParameter((Parameter)object);
}
}
attribute.init();
return attribute;
}
public Component processComponent(final StaxReader parser)
throws XMLStreamException, IOException {
final String area = parser.getAttributeValue(null, "area");
final String name = parser.getAttributeValue(null, "name");
final String file = parser.getAttributeValue(null, "file");
final Component component = new Component(area, name, file);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof ActionConfig) {
component.addAction((ActionConfig)object);
} else if (object instanceof Style) {
component.addStyle((Style)object);
} else if (object instanceof Script) {
component.addScript((Script)object);
} else if (object instanceof OnLoad) {
component.addOnLoad((OnLoad)object);
} else if (object instanceof Field) {
component.addField((Field)object);
}
}
return component;
}
public ComponentInclude processComponentInclude(final StaxReader parser)
throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String area = parser.getAttributeValue(null, "area");
final Component component = (Component)this.config.getComponent(name).clone();
final ComponentInclude componentInclude = new ComponentInclude(area, component);
parser.skipSubTree();
return componentInclude;
}
public Menu processDynamicMenu(final StaxReader parser) throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
String pageRef = parser.getAttributeValue(null, "pageRef");
String title = parser.getAttributeValue(null, "title");
final String anchor = parser.getAttributeValue(null, "anchor");
String url = parser.getAttributeValue(null, "uri");
final String condition = parser.getAttributeValue(null, "condition");
final String loaderClassName = parser.getAttributeValue(null, "class");
if (pageRef != null) {
pageRef = pageRef.trim();
if (!pageRef.equals("")) {
try {
final Page page = this.config.getPageByName(pageRef);
url = page.getPath();
if (title == null || title.trim().equals("")) {
title = page.getTitle();
}
} catch (final PageNotFoundException e) {
log.error(e.getMessage(), e);
getContext().addError(e.getMessage(), e, parser.getLocation());
}
}
}
try {
final Class loaderClass = Class.forName(loaderClassName);
final Constructor loaderCons = loaderClass.getConstructor(new Class[] {
Config.class
});
final MenuItemLoader loader = (MenuItemLoader)loaderCons.newInstance(new Object[] {
this.config
});
final DynamicMenu menu = new DynamicMenu(name, title, url, anchor, condition, loader);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof WebProperty) {
final WebProperty webProperty = (WebProperty)object;
loader.setProperty(webProperty.getName(), webProperty.getValue());
}
}
return menu;
} catch (final InvocationTargetException e) {
final Throwable t = e.getCause();
log.error(t.getMessage(), t);
getContext().addError(t.getMessage(), t, parser.getLocation());
} catch (final Exception e) {
log.error(e.getMessage(), e);
getContext().addError(e.getMessage(), e, parser.getLocation());
}
return null;
}
public ElementComponent processElementComponent(final StaxReader parser)
throws XMLStreamException, IOException {
final String area = parser.getAttributeValue(null, "area");
final String name = parser.getAttributeValue(null, "name");
final String attribute = parser.getAttributeValue(null, "attribute");
final ElementComponent component = new ElementComponent(area, name, attribute);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof ActionConfig) {
component.addAction((ActionConfig)object);
} else if (object instanceof Style) {
component.addStyle((Style)object);
} else if (object instanceof Script) {
component.addScript((Script)object);
} else if (object instanceof OnLoad) {
component.addOnLoad((OnLoad)object);
} else if (object instanceof Field) {
component.addField((Field)object);
}
}
return component;
}
public Field processField(final StaxReader parser) throws XMLStreamException, IOException {
final String script = parser.getAttributeValue(null, "script");
final Field field = new Field(script);
parser.skipSubTree();
return field;
}
public Config processIafConfig(final StaxReader parser) throws XMLStreamException, IOException {
final String basePath = parser.getAttributeValue(null, "basePath");
if (!this.child) {
this.config = new Config(this.servletContext, basePath);
WebUiContext.set(new WebUiContext(this.config, null, null, null, null));
getContext().setAttribute("com.revolsys.iaf.core.Config", this.config);
}
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof Page) {
this.config.addPage((Page)object);
} else if (object instanceof Layout) {
this.config.addLayout((Layout)object);
} else if (object instanceof Component) {
this.config.addComponent((Component)object);
} else if (object instanceof Menu) {
this.config.addMenu((Menu)object);
}
}
return this.config;
}
public Config processImport(final StaxReader parser) throws IOException {
final String resource = parser.getAttributeValue(null, "resource");
if (resource != null) {
final URL resourceUrl = getClass().getResource(resource);
if (resourceUrl != null) {
final XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setXMLReporter(getContext());
final StaxReader importParser = StaxReader.newXmlReader(factory, resourceUrl.openStream());
importParser.skipToStartElement();
if (importParser.getEventType() == XMLStreamConstants.START_ELEMENT) {
new IafConfigXmlProcessor(this).process(importParser);
}
}
}
parser.skipSubTree();
return null;
}
public JavaComponent processJavaComponent(final StaxReader parser)
throws XMLStreamException, IOException {
final String area = parser.getAttributeValue(null, "area");
final String name = parser.getAttributeValue(null, "name");
final String className = parser.getAttributeValue(null, "class");
final JavaComponent component = new JavaComponent(area, name, className);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof ActionConfig) {
component.addAction((ActionConfig)object);
} else if (object instanceof Style) {
component.addStyle((Style)object);
} else if (object instanceof Script) {
component.addScript((Script)object);
} else if (object instanceof OnLoad) {
component.addOnLoad((OnLoad)object);
} else if (object instanceof Field) {
component.addField((Field)object);
} else if (object instanceof WebProperty) {
final WebProperty webProperty = (WebProperty)object;
component.setProperty(webProperty.getName(), webProperty.getValue());
}
}
return component;
}
public Layout processLayout(final StaxReader parser) throws XMLStreamException, IOException {
final String areaName = parser.getAttributeValue(null, "area");
final String name = parser.getAttributeValue(null, "name");
final String file = parser.getAttributeValue(null, "file");
boolean page = false;
final String pageAttr = parser.getAttributeValue(null, "page");
if (pageAttr != null && (pageAttr.equals("yes") || pageAttr.equals("true"))) {
page = true;
}
final Layout layout = new Layout(areaName, name, file, page);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof ActionConfig) {
layout.addAction((ActionConfig)object);
} else if (object instanceof Style) {
layout.addStyle((Style)object);
} else if (object instanceof Script) {
layout.addScript((Script)object);
} else if (object instanceof OnLoad) {
layout.addOnLoad((OnLoad)object);
} else if (object instanceof Field) {
layout.addField((Field)object);
} else if (object instanceof Area) {
final Area area = (Area)object;
layout.addArea(area);
final String componentName = area.getComponentName();
if (componentName != null && componentName.length() > 0) {
final Component component = this.config.getComponent(componentName);
layout.setComponent(area.getName(), (Component)component.clone());
}
}
}
return layout;
}
public LayoutInclude processLayoutInclude(final StaxReader parser)
throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String area = parser.getAttributeValue(null, "area");
final Layout layout = (Layout)this.config.getLayout(name).clone();
final LayoutInclude layoutInclude = new LayoutInclude(area, layout);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof LayoutInclude) {
final LayoutInclude childInclude = (LayoutInclude)object;
layout.setComponent(childInclude.getArea(), childInclude.getLayout());
} else if (object instanceof ComponentInclude) {
final ComponentInclude componentInclude = (ComponentInclude)object;
layout.setComponent(componentInclude.getArea(), componentInclude.getComponent());
} else if (object instanceof Component) {
final Component component = (Component)object;
layout.setComponent(component.getArea(), component);
}
}
return layoutInclude;
}
public Menu processMenu(final StaxReader parser) throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
String pageRef = parser.getAttributeValue(null, "pageRef");
String title = parser.getAttributeValue(null, "title");
final String anchor = parser.getAttributeValue(null, "anchor");
String url = parser.getAttributeValue(null, "uri");
final String condition = parser.getAttributeValue(null, "condition");
if (pageRef != null) {
pageRef = pageRef.trim();
final Page page = getPageByRef(parser, pageRef.trim());
if (page != null) {
url = page.getFullPath();
if (title == null || title.trim().equals("")) {
title = page.getTitle();
}
}
}
Menu menu = null;
try {
menu = new Menu(name, title, url, anchor, condition);
} catch (final Exception e) {
getContext().addError("Error creating menu item: " + e.getMessage(), e, parser.getLocation());
}
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof MenuItem) {
menu.addMenuItem((MenuItem)object);
} else if (object instanceof Parameter) {
try {
menu.addParameter((Parameter)object);
} catch (final Exception e) {
getContext().addError("Error adding menu parameter: " + e.getMessage(), e,
parser.getLocation());
}
} else if (object instanceof WebProperty) {
menu.addProperty((WebProperty)object);
}
}
return menu;
}
public Menu processMenuInclude(final StaxReader parser) throws XMLStreamException, IOException {
final String refname = parser.getAttributeValue(null, "refname");
final String name = parser.getAttributeValue(null, "name");
Menu menu = this.config.getMenu(refname);
if (name != null) {
menu = (Menu)menu.clone();
menu.setName(name);
}
parser.skipSubTree();
return menu;
}
public MenuItem processMenuItem(final StaxReader parser) throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String pageRef = parser.getAttributeValue(null, "pageRef");
final String title = parser.getAttributeValue(null, "title");
final String anchor = parser.getAttributeValue(null, "anchor");
final String url = parser.getAttributeValue(null, "uri");
final String condition = parser.getAttributeValue(null, "condition");
MenuItem menuItem = null;
try {
if (pageRef != null) {
menuItem = new PageRefMenuItem(name, title, pageRef.trim(), anchor, condition);
} else {
menuItem = new MenuItem(name, title, url, anchor, condition);
}
} catch (final Exception e) {
getContext().addError("Error creating menu item: " + e.getMessage(), e, parser.getLocation());
return null;
}
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof Parameter) {
try {
menuItem.addParameter((Parameter)object);
} catch (final Exception e) {
getContext().addError("Error creating menu item parameter: " + e.getMessage(), e,
parser.getLocation());
}
} else if (object instanceof WebProperty) {
menuItem.addProperty((WebProperty)object);
}
}
return menuItem;
}
public OnLoad processOnLoad(final StaxReader parser) throws XMLStreamException, IOException {
final String script = parser.getAttributeValue(null, "script");
final OnLoad onLoad = new OnLoad(script);
parser.skipSubTree();
return onLoad;
}
public Page processPage(final StaxReader parser) throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String title = parser.getAttributeValue(null, "title");
final String path = parser.getAttributeValue(null, "path");
final boolean secure = getBooleanAttribute(parser, "secure");
final Page page = new Page(name, title, path, secure);
final Page parentPage = getCurrentPage();
if (parentPage != null) {
page.setParent(parentPage);
this.config.addPage(page);
}
this.pageStack.add(page);
while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
final Object object = process(parser);
if (object instanceof ActionConfig) {
page.addAction((ActionConfig)object);
} else if (object instanceof Style) {
page.addStyle((Style)object);
} else if (object instanceof Script) {
page.addScript((Script)object);
} else if (object instanceof OnLoad) {
page.addOnLoad((OnLoad)object);
} else if (object instanceof LayoutInclude) {
final LayoutInclude layoutInclude = (LayoutInclude)object;
page.setLayout(layoutInclude.getLayout());
} else if (object instanceof Page) {
page.addPage((Page)object);
} else if (object instanceof Menu) {
page.addMenu((Menu)object);
} else if (object instanceof Argument) {
page.addArgument((Argument)object);
} else if (object instanceof Attribute) {
page.addField((Attribute)object);
}
}
this.pageStack.removeLast();
return page;
}
public Parameter processParameter(final StaxReader parser)
throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String value = parser.getAttributeValue(null, "value");
final Parameter parameter = new Parameter(name, value);
parser.skipSubTree();
return parameter;
}
public WebProperty processProperty(final StaxReader parser)
throws XMLStreamException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String value = parser.getAttributeValue(null, "value");
final WebProperty webProperty = new WebProperty(name, value);
parser.skipSubTree();
return webProperty;
}
public Script processScript(final StaxReader parser) throws XMLStreamException, IOException {
final String file = parser.getAttributeValue(null, "file");
final Script script = new Script(file);
parser.skipSubTree();
return script;
}
public Style processStyle(final StaxReader parser) throws XMLStreamException, IOException {
final String file = parser.getAttributeValue(null, "file");
final Style style = new Style(file);
parser.skipSubTree();
return style;
}
}