Xebra Create Tag Library

Revision as of 12:44, 31 August 2009 by Sandrod (Talk | contribs) (Adding Tags)

This tutorial shows you how you can create a tag library for your own needs. It makes sense to add a custom library if some functionality recurs in your project(s). We will create a simple tag library ("font") with a tag with the ability to format text as bold (bold).

Setting up

Every tag library needs a unique namespace (like xeb or page). We create a folder in $FONT_TAG_LIBRARY where we put all our configuration and tag library files. The API of our tag library is defined in a file called config.taglib and has to be located in $FONT_TAG_LIBRARY. Since we don't have any tags yet, the file will just contain a skeleton:

<taglib id="font">
</taglib>

With this configuration we created a tag library with the namespace "font" and no tags. Since tag libraries are used as libraries we need to add a font_tag_library.ecf in the same folder as well:

<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-5-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-5-0 http://www.eiffel.com/developers/xml/configuration-1-5-0.xsd" name="font_tag_library" uuid="491B4344-79AF-43CB-891B-47EDEAC11056" library_target="font_tag_library">
	<target name="font_tag_library">
		<root all_classes="true"/>
		<option full_class_checking="true" syntax="transitional">
			<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
		</option>
		<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
		<library name="xebra_ast_elements" location="$XEBRA_DEV\eiffel_projects\library\xebra_ast_elements\xebra_ast_elements-voidunsafe.ecf"/>
		<library name="xebra_tags" location="$XEBRA_DEV\eiffel_projects\library\xebra_tags\xebra_tags-voidunsafe.ecf"/>
		<library name="xebra_utilities" location="$XEBRA_DEV\eiffel_projects\library\xebra_utilities\xebra_utilities-voidunsafe.ecf"/>
		<cluster name="font_tag_library" location=".\" recursive="true">
			<file_rule>
				<exclude>/EIFGENs$</exclude>
				<exclude>/.svn$</exclude>
				<exclude>/CVS$</exclude>
			</file_rule>
		</cluster>
	</target>
</system>

Adding Tags

To add our boldifying tag we need to add it to the config.taglib on the one hand and implement an eiffel class representing it on the other. The config.taglib looks like this now:

<taglib id="xeb">
    <tag id="bold" class="FONT_BOLD_TAG">		
        <attribute id="text" optional="True"/>
    </tag>
</taglib>

Note that we added a argument to the tag: text. It is defined to be optional, so there is a default value for it. The corresponding class is defined with class, in this case FONT_BOLD_TAG. The latter has to inherit from XTAG_TAG_SERIALIZER and implement a few features. In our example:

class
	FONT_BOLD_TAG
 
inherit
	XTAG_TAG_SERIALIZER
		redefine
			generates_render
		end
 
create
	make
 
feature -- Initialization
 
	make
			--
		do
			make_base
			create {XTAG_TAG_VALUE_ARGUMENT} text.make ("default_text")
		end
 
feature -- Access
 
	text: XTAG_TAG_ARGUMENT
			-- The text which should be displayed bold
 
feature -- Implementation
 
	internal_generate (a_servlet_class: XEL_SERVLET_CLASS_ELEMENT; a_variable_table: HASH_TABLE [ANY, STRING])
			-- <Precursor>
		do
			a_servlet_class.render_html_page.
				append_output_expression 
					("<b>%"" + text.value (current_controller_id) + "%"</b>")
		end
 
	internal_put_attribute (a_id: STRING; a_attribute: XTAG_TAG_ARGUMENT)
			-- <Precursor>
		do
			if id.is_equal ("text") then
				text := a_attribute
			end
		end
 
	generates_render: BOOLEAN = True

For our tag we needed to implement the two features internal_generate and internal_put_attribute. The former has the task to generate all code in the servlet. In our case this is a print on the HTML result. The latter - internal_put_attribute - handles attributes of the tag. Here we just read the value and save it into text for further reuse in the rendering. Finally we redefined generates_render. This tells the generator that the tag creates expressions in the render feature. This feature redefinition is not needed, but will add debug information in the generated servlet file.