All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.metawidget.statically.StaticMetawidget Maven / Gradle / Ivy

There is a newer version: 4.2
Show newest version
// Metawidget
//
// This library 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 library 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 library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package org.metawidget.statically;

import static org.metawidget.inspector.InspectionResultConstants.*;

import java.io.Writer;
import java.util.List;
import java.util.Map;

import org.metawidget.config.iface.ConfigReader;
import org.metawidget.iface.MetawidgetException;
import org.metawidget.inspectionresultprocessor.iface.InspectionResultProcessor;
import org.metawidget.inspector.iface.Inspector;
import org.metawidget.layout.iface.Layout;
import org.metawidget.pipeline.w3c.W3CPipeline;
import org.metawidget.statically.StaticUtils.IndentedWriter;
import org.metawidget.util.simple.PathUtils;
import org.metawidget.util.simple.PathUtils.TypeAndNames;
import org.metawidget.util.simple.StringUtils;
import org.metawidget.widgetbuilder.iface.WidgetBuilder;
import org.metawidget.widgetprocessor.iface.WidgetProcessor;
import org.w3c.dom.Element;

/**
 * Base Metawidget for static code generation.
 * 

* Although Metawidget focuses on runtime UI generation, there are a category of * applications that require static code generation instead. It is still possible to make full use * of Metawidget's 5 stage pipeline (inspectors, inspection result processors, widget builders, * widget processors, layouts) during static code generation. *

* An important requirement for static code generation is the Metawidget should not rely on the * technology being generated being available. For example, a static JSF Metawidget should not rely * on FacesContext.getCurrentInstance. Architectually, this makes all static * Metawidgets more similar to each other than to their corresponding runtime version. For example, * the static JSF Metawidget is more similar to the static Spring Metawidget than it is to the * runtime JSF Metawidget. Therefore, it makes sense to have a StaticMetawidget base * class. * * @author Richard Kennard */ public abstract class StaticMetawidget extends BaseStaticWidget { // // Private members // /** * Path to inspect. */ private String mPath; private Pipeline mPipeline; // // Constructor // public StaticMetawidget() { mPipeline = newPipeline(); } // // Public methods // public void setPath( String path ) { mPath = path; } public String getPath() { return mPath; } public void setConfigReader( ConfigReader configReader ) { mPipeline.setConfigReader( configReader ); } public String getConfig() { return (String) mPipeline.getConfig(); } public void setConfig( String config ) { mPipeline.setConfig( config ); } public void setMaximumInspectionDepth( int maximumInspectionDepth ) { mPipeline.setMaximumInspectionDepth( maximumInspectionDepth ); } public String getLabelString( Map attributes ) { if ( attributes == null ) { return ""; } // Explicit label String label = attributes.get( LABEL ); if ( label != null ) { // (may be forced blank) if ( "".equals( label ) ) { return null; } return label.trim(); } // Default name String name = attributes.get( NAME ); if ( name != null ) { return StringUtils.uncamelCase( name ); } return ""; } public boolean isReadOnly() { return mPipeline.isReadOnly(); } public void setReadOnly( boolean readOnly ) { mPipeline.setReadOnly( readOnly ); } public Inspector getInspector() { return mPipeline.getInspector(); } public void setInspector( Inspector inspector ) { mPipeline.setInspector( inspector ); } /** * Useful for WidgetBuilders to perform nested inspections (eg. for Collections). */ public String inspect( Object toInspect, String type, String... names ) { return mPipeline.inspect( toInspect, type, names ); } /** * Useful for WidgetBuilders to setup nested Metawidgets (eg. for wrapping them in a * panelGroup). */ public void initNestedMetawidget( StaticMetawidget nestedMetawidget, Map attributes ) { // Don't reconfigure... nestedMetawidget.setConfig( null ); // ...instead, copy runtime values mPipeline.initNestedPipeline( nestedMetawidget.mPipeline, attributes ); if ( nestedMetawidget.getPath() == null ) { nestedMetawidget.setPath( mPath + StringUtils.SEPARATOR_FORWARD_SLASH_CHAR + attributes.get( NAME ) ); } } @SuppressWarnings( { "unchecked" } ) public void setInspectionResultProcessors( InspectionResultProcessor... inspectionResultProcessors ) { mPipeline.setInspectionResultProcessors( (InspectionResultProcessor[]) inspectionResultProcessors ); } public WidgetBuilder getWidgetBuilder() { return mPipeline.getWidgetBuilder(); } @SuppressWarnings( { "unchecked", "rawtypes" } ) public void setWidgetBuilder( WidgetBuilder widgetBuilder ) { mPipeline.setWidgetBuilder( (WidgetBuilder) widgetBuilder ); } @SuppressWarnings( { "unchecked", "rawtypes" } ) public void addWidgetProcessor( WidgetProcessor widgetProcessor ) { mPipeline.addWidgetProcessor( (WidgetProcessor) widgetProcessor ); } public List> getWidgetProcessors() { return mPipeline.getWidgetProcessors(); } @SuppressWarnings( { "unchecked" } ) public void setWidgetProcessors( WidgetProcessor... widgetProcessors ) { mPipeline.setWidgetProcessors( (WidgetProcessor[]) widgetProcessors ); } public T getWidgetProcessor( Class widgetProcessorClass ) { return mPipeline.getWidgetProcessor( widgetProcessorClass ); } @SuppressWarnings( { "unchecked", "rawtypes" } ) public void removeWidgetProcessor( WidgetProcessor widgetProcessor ) { mPipeline.removeWidgetProcessor( (WidgetProcessor) widgetProcessor ); } /** * Useful for WidgetBuilders. */ public Layout getLayout() { return mPipeline.getLayout(); } @SuppressWarnings( { "unchecked", "rawtypes" } ) public void setLayout( Layout layout ) { mPipeline.setLayout( (Layout) layout ); } @Override public void write( Writer writer ) { write( writer, -1 ); } /** * Write the Metawidget output using the given Writer. * * @param initialIndent * the initialIndent that will be applied to every line. 0 for no initial indent. -1 * for no subsequent indenting either */ public void write( Writer writer, int initialIndent ) { try { mPipeline.buildWidgets( inspect() ); Writer writerToUse = writer; if ( initialIndent >= 0 ) { writerToUse = new IndentedWriter( writer, initialIndent ); } super.write( writerToUse ); } catch ( Exception e ) { throw MetawidgetException.newException( e ); } } // // Protected methods // /** * Instantiate the Pipeline used by this Metawidget. *

* Subclasses wishing to use their own Pipeline should override this method to instantiate their * version. */ protected Pipeline newPipeline() { return new Pipeline(); } protected void startBuild() { getChildren().clear(); } /** * @param element * the parent element that will be iterated over */ protected void beforeBuildCompoundWidget( Element element ) { // Do nothing by default } protected Element inspect() { if ( mPath == null ) { return null; } TypeAndNames typeAndNames = PathUtils.parsePath( mPath, StringUtils.SEPARATOR_FORWARD_SLASH_CHAR ); String type = typeAndNames.getType(); return mPipeline.inspectAsDom( null, type, typeAndNames.getNamesAsArray() ); } protected abstract String getDefaultConfiguration(); // // Inner class // /** * Internal Metawidget pipeline. *

* We must use <StaticWidget, StaticWidget, StaticMetawidget> because that is what * org.metawidget.statically.layout.SimpleLayout uses. Therefore we must expose * setLayout(<StaticWidget, StaticWidget, StaticMetawidget>). *

* We also need subclasses such as * setLayout(<StaticXmlWidget, StaticXmlWidget, StaticXmlMetawidget>). So we must * allow extensions of StaticWidget (eg. W extends StaticWidget) during * setLayout. *

* However this causes problems because if W extends StaticWidget then we cannot * guarantee that M extends W and also extends StaticMetawidget. Java * Generics cannot express this, even with Bounded Type Parameters. Hence some * SuppressWarnings above. */ protected class Pipeline extends W3CPipeline { // // Protected methods // @Override protected String getDefaultConfiguration() { return StaticMetawidget.this.getDefaultConfiguration(); } @Override protected Map getAdditionalAttributes( StaticWidget tag ) { return null; } @Override protected void startBuild() { StaticMetawidget.this.startBuild(); super.startBuild(); } @Override protected void buildCompoundWidget( Element element ) throws Exception { StaticMetawidget.this.beforeBuildCompoundWidget( element ); super.buildCompoundWidget( element ); } @Override protected StaticMetawidget buildNestedMetawidget( final Map attributes ) throws Exception { StaticMetawidget metawidgetTag = StaticMetawidget.this.getClass().newInstance(); StaticMetawidget.this.initNestedMetawidget( metawidgetTag, attributes ); return metawidgetTag; } @Override protected StaticMetawidget getPipelineOwner() { return StaticMetawidget.this; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy