summaryrefslogtreecommitdiff
path: root/orkweb/src/net/sf/oreka/tapestry
diff options
context:
space:
mode:
Diffstat (limited to 'orkweb/src/net/sf/oreka/tapestry')
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/MainMenu.html31
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/MainMenu.java39
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/MainMenu.jwc8
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/MainMenu.properties2
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TableColumn.java68
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TableHeader.html15
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TableHeader.java81
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TableHeader.jwc13
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TablePaging.html90
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TablePaging.java106
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TablePaging.jwc17
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TablePaging.properties4
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/TableState.java143
-rw-r--r--orkweb/src/net/sf/oreka/tapestry/my.library13
14 files changed, 630 insertions, 0 deletions
diff --git a/orkweb/src/net/sf/oreka/tapestry/MainMenu.html b/orkweb/src/net/sf/oreka/tapestry/MainMenu.html
new file mode 100644
index 0000000..8873c57
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/MainMenu.html
@@ -0,0 +1,31 @@
+<!-- *** Main Menu *** -->
+<link jwcid="@If" condition="false" href="orekastyle.css" rel="stylesheet" type="text/css"/>
+<table width="100%" class="menuContainer">
+ <tr>
+ <td align="left">
+ <table class="menubuttons">
+ <tr>
+ <td jwcid="@Any" class="ognl:pageName=='Home'? 'on' : ''">
+ <a jwcid="@PageLink" page="Home">
+ <span key="Home">Home</span>
+ </a>
+ </td>
+ <td jwcid="@Any" class="ognl:pageName=='RecSegments'? 'on' : ''">
+ <a jwcid="@PageLink" page="RecSegments">
+ <span key="RecSegments">Calls</span>
+ </a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="right">
+ <table class="menubuttons">
+ <tr>
+ <td>
+ <span jwcid="@ServiceLink" service="ognl:@org.apache.tapestry.Tapestry@RESTART_SERVICE">Logout</span>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/orkweb/src/net/sf/oreka/tapestry/MainMenu.java b/orkweb/src/net/sf/oreka/tapestry/MainMenu.java
new file mode 100644
index 0000000..2e4e49f
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/MainMenu.java
@@ -0,0 +1,39 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+package net.sf.oreka.tapestry;
+
+import org.apache.tapestry.BaseComponent;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.annotations.Persist;
+
+@ComponentClass
+public abstract class MainMenu extends BaseComponent {
+
+ public void myAction(IRequestCycle cycle) {
+
+ setHighlight(!getHighlight());
+ cycle.activate("Home");
+ }
+
+ @Persist
+ public abstract boolean getHighlight();
+ public abstract void setHighlight(boolean highlight);
+
+ @Parameter
+ public abstract String getPageName();
+ public abstract void setPageName(String name);
+
+}
diff --git a/orkweb/src/net/sf/oreka/tapestry/MainMenu.jwc b/orkweb/src/net/sf/oreka/tapestry/MainMenu.jwc
new file mode 100644
index 0000000..b7c6e90
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/MainMenu.jwc
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE component-specification
+ PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
+ "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
+
+<component-specification class="net.sf.oreka.tapestry.MainMenu"
+ allow-informal-parameters="no">
+</component-specification> \ No newline at end of file
diff --git a/orkweb/src/net/sf/oreka/tapestry/MainMenu.properties b/orkweb/src/net/sf/oreka/tapestry/MainMenu.properties
new file mode 100644
index 0000000..22b8416
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/MainMenu.properties
@@ -0,0 +1,2 @@
+RecSegments=Browse
+Home=Welcome \ No newline at end of file
diff --git a/orkweb/src/net/sf/oreka/tapestry/TableColumn.java b/orkweb/src/net/sf/oreka/tapestry/TableColumn.java
new file mode 100644
index 0000000..29de8f3
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TableColumn.java
@@ -0,0 +1,68 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+/**
+ *
+ */
+package net.sf.oreka.tapestry;
+
+public class TableColumn {
+
+ String message;
+ String key;
+ boolean sortable;
+ /**
+ * @return Returns the isSortable.
+ */
+ public boolean isSortable() {
+ return sortable;
+ }
+
+
+ /**
+ * @param isSortable The isSortable to set.
+ */
+ public void setSortable(boolean sortable) {
+ this.sortable = sortable;
+ }
+
+
+ /**
+ * @return Returns the key.
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * @param key The key to set.
+ */
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ /**
+ * @return Returns the message.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * @param message The message to set.
+ */
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+}
diff --git a/orkweb/src/net/sf/oreka/tapestry/TableHeader.html b/orkweb/src/net/sf/oreka/tapestry/TableHeader.html
new file mode 100644
index 0000000..149a662
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TableHeader.html
@@ -0,0 +1,15 @@
+<tr class="header">
+ <td jwcid="@Foreach" source="ognl:columns" value="ognl:column" element="td">
+ <span jwcid="@If" condition="ognl:column.sortable">
+ <a jwcid="@DirectLink" listener="ognl:listeners.columnClickAction" parameters="ognl:column.key">
+ <span jwcid="@Insert" value="ognl:column.message">sortableColumn</span>
+ </a>
+ </span>
+ <span jwcid="@If" condition="ognl:!column.sortable">
+ <span jwcid="@Insert" value="ognl:column.message">nonSortableColumn</span>
+ </span>
+ </td>
+<tr>
+
+
+
diff --git a/orkweb/src/net/sf/oreka/tapestry/TableHeader.java b/orkweb/src/net/sf/oreka/tapestry/TableHeader.java
new file mode 100644
index 0000000..6b8ccc2
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TableHeader.java
@@ -0,0 +1,81 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+/**
+ *
+ */
+package net.sf.oreka.tapestry;
+
+import java.util.*;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.*;
+import org.apache.tapestry.*;
+
+
+public abstract class TableHeader extends BaseComponent {
+
+ static Logger logger = Logger.getLogger(TableHeader.class);
+
+ public abstract TableState getTableState();
+ public abstract void setTableState(TableState state);
+
+ //private String columns;
+ public abstract String getColumnsCSV();
+ public abstract void setColumnsCSV(String columns);
+
+
+ public List getColumns() {
+ String[] columnsArray = StringUtils.split(getColumnsCSV(),", ");
+ //logger.log(Level.INFO, "ColumnsCSV: "+getColumnsCSV());
+
+ List columns = new ArrayList();
+ for (int i=0; i<columnsArray.length; i++) {
+ TableColumn column = new TableColumn();
+ column.setSortable(true);
+ String columnKey = columnsArray[i];
+ if (columnsArray[i].charAt(0) == '!') {
+ column.setSortable(false);
+ columnKey = columnsArray[i].substring(1);
+ }
+ column.setKey(columnKey);
+ String LocalizedMessage = getPage().getMessages().getMessage(columnKey);
+ column.setMessage(LocalizedMessage);
+ columns.add(column);
+ }
+ return columns;
+ }
+
+ public abstract void setColumn(TableColumn col);
+ public abstract TableColumn getColumn();
+
+ /**
+ *
+ */
+ public TableHeader() {
+ }
+
+ public void columnClickAction(IRequestCycle cycle) {
+
+ Object[] parameters = cycle.getServiceParameters();
+ String column = (String)parameters[0];
+ if (!column.equals(getTableState().getOrderBy())) {
+ getTableState().setOrderBy(column);
+ getTableState().setAscending(true);
+ }
+ else {
+ // Toggle direction
+ getTableState().setAscending(!getTableState().isAscending());
+ }
+ setTableState(getTableState());
+ }
+}
diff --git a/orkweb/src/net/sf/oreka/tapestry/TableHeader.jwc b/orkweb/src/net/sf/oreka/tapestry/TableHeader.jwc
new file mode 100644
index 0000000..0755a7a
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TableHeader.jwc
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE component-specification
+ PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
+ "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
+
+<component-specification class="net.sf.oreka.tapestry.TableHeader"
+ allow-informal-parameters="no">
+
+ <parameter name="tableState" type="net.sf.oreka.tapestry.TableState" direction="auto" required="yes"/>
+ <parameter name="columnsCSV" type="java.lang.String" direction="auto" required="yes"/>
+
+ <property-specification name="column" type="net.sf.oreka.tapestry.TableColumn"/>
+</component-specification> \ No newline at end of file
diff --git a/orkweb/src/net/sf/oreka/tapestry/TablePaging.html b/orkweb/src/net/sf/oreka/tapestry/TablePaging.html
new file mode 100644
index 0000000..9adc8d1
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TablePaging.html
@@ -0,0 +1,90 @@
+<!--<style type="text/css">
+ .cursor {
+ background-color: white;
+ text-align: right;
+ padding-right: 0;
+ }
+
+ .cursor div {
+ border-top: solid 2px #930512;
+ background-color: #FD0D24;
+ border-bottom: solid 2px #930512;
+ text-align: right;
+ color: white;
+ float: left;
+ padding-top: 0;
+ height: 1em;
+ }
+
+ .bar {
+ background-color: white;
+ text-align: right;
+ padding-right: 0;
+ }
+
+ .bar div {
+ border-top: solid 2px #03144B;
+ background-color: #0930AC;
+ border-bottom: solid 2px #03144B;
+ text-align: right;
+ color: white;
+ float: left;
+ padding-top: 0;
+ height: 1em;
+
+
+</style>-->
+
+<table width="100%" class="paging">
+ <tr class="odd">
+ <td align="left">
+ <table>
+ <tr>
+ <td>
+ <a jwcid="@DirectLink" listener="ognl:listeners.firstPageAction">
+ <img jwcid="@Image" image="asset:first" alt="First"/>
+ </a>
+ </td>
+ <td>
+ <a jwcid="@DirectLink" listener="ognl:listeners.previousPageAction">
+ <img jwcid="@Image" image="asset:previous" alt="First"/>
+ </a>
+ </td>
+ <td>
+ <a jwcid="@DirectLink" listener="ognl:listeners.nextPageAction">
+ <img jwcid="@Image" image="asset:next" alt="First"/>
+ </a>
+ </td>
+ <td>
+ <a jwcid="@DirectLink" listener="ognl:listeners.lastPageAction">
+ <img jwcid="@Image" image="asset:last" alt="First"/>
+ </a>
+ </td>
+ <td nowrap="true">
+ Page <span jwcid="@Insert" value="ognl:tableState.currentPage"/>/<span jwcid="@Insert" value="ognl:tableState.numPages"/>
+ </td>
+ <td nowrap="true">
+ <span jwcid="@Insert" value="ognl:tableState.numResults"/> Results
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td width="100%">
+ &nbsp;
+ </td>
+ </tr>
+ <!--*** Slider ***-->
+ <tr>
+ <td colspan="2">
+ <table width="100%">
+ <tr>
+ <td jwcid="@Foreach" source="ognl:sliderPositions" value="ognl:sliderPosition" element="td" class="ognl:tableState.sliderPosition == sliderPosition ? 'cursor' : 'bar'">
+ <a jwcid="@DirectLink" listener="ognl:listeners.sliderClickAction" parameters="ognl:sliderPosition">
+ <div style="width: 100%">&nbsp;</div>
+ </a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
diff --git a/orkweb/src/net/sf/oreka/tapestry/TablePaging.java b/orkweb/src/net/sf/oreka/tapestry/TablePaging.java
new file mode 100644
index 0000000..e401543
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TablePaging.java
@@ -0,0 +1,106 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+/**
+ *
+ */
+package net.sf.oreka.tapestry;
+
+import java.util.*;
+import org.apache.log4j.*;
+import org.apache.tapestry.*;
+
+
+public abstract class TablePaging extends BaseComponent {
+
+ static Logger logger = Logger.getLogger(TablePaging.class);
+
+ public abstract TableState getTableState();
+ public abstract void setTableState(TableState state);
+
+ Integer sliderPosition;
+
+ public void firstPageAction(IRequestCycle cycle) {
+ getTableState().setNumResults(0);
+ setTableState(getTableState()); // persist !
+ }
+
+ public void previousPageAction(IRequestCycle cycle) {
+ TableState ps = getTableState();
+ if ( (ps.getCurrentOffset() - ps.getResultsPerPage()) >= 0 ) {
+ ps.setCurrentOffset(ps.getCurrentOffset() - ps.getResultsPerPage());
+ }
+ setTableState(getTableState()); // persist !
+ }
+
+ public void nextPageAction(IRequestCycle cycle) {
+ //logger.log(Level.INFO, "before:" + getPagingState().getCurrentPage());
+ //getPagingState().setCurrentPage(getPagingState().getCurrentPage()+1);
+ //logger.log(Level.INFO, "after:" + getPagingState().getCurrentPage());
+
+ TableState ps = getTableState();
+ if ( (ps.getCurrentOffset() + ps.getResultsPerPage()) < ps.getNumResults() ) {
+ ps.setCurrentOffset(ps.getCurrentOffset() + ps.getResultsPerPage());
+ }
+ setTableState(getTableState()); // persist !
+ }
+
+ public void lastPageAction(IRequestCycle cycle) {
+
+ TableState ps = getTableState();
+ double numPages = (double)ps.getNumResults() / ps.getResultsPerPage();
+ numPages = java.lang.Math.ceil(numPages);
+ //int numWholePages = ps.getNumResults() / ps.getResultsPerPage();
+ //int remainder = ps.getNumResults() % ps.getResultsPerPage();
+ //int lastPageOffset = 0;
+ //if (remainder > 0) {
+ // lastPageOffset = numWholePages * ps.getResultsPerPage();
+ //}
+ //else if (numWholePages > 0){
+ // lastPageOffset = (numWholePages - 1) * ps.getResultsPerPage();
+ //}
+ int lastPageOffset = 0;
+ if (numPages >= 1) {
+ lastPageOffset = (int)(numPages-1) * ps.getResultsPerPage();
+ }
+ ps.setCurrentOffset(lastPageOffset);
+ setTableState(getTableState()); // persist !
+ }
+
+ public void sliderClickAction(IRequestCycle cycle) {
+
+ Object[] parameters = cycle.getServiceParameters();
+ Integer sliderPosition = (Integer)parameters[0];
+
+ TableState ts = getTableState();
+ ts.setSliderPosition(sliderPosition);
+ double newOffset = ((double)ts.getNumResults() / getSliderPositions().size()) * sliderPosition.intValue();
+ ts.setCurrentOffset((int)newOffset);
+ logger.log(Level.INFO, "Slider: pos:" + sliderPosition.intValue() + " offset:" + newOffset);
+ setTableState(getTableState()); // persist !
+ }
+
+ /**
+ * @return Returns the sliderPositions.
+ */
+ public List getSliderPositions() {
+
+ ArrayList sliderPositions = new ArrayList();
+ int numPositions = java.lang.Math.min(getTableState().getNumPages(), 20);
+ for(int i=0;i<numPositions;i++) {
+ sliderPositions.add(new Integer(i));
+ }
+ return sliderPositions;
+ }
+
+}
diff --git a/orkweb/src/net/sf/oreka/tapestry/TablePaging.jwc b/orkweb/src/net/sf/oreka/tapestry/TablePaging.jwc
new file mode 100644
index 0000000..2e19947
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TablePaging.jwc
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE component-specification
+ PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
+ "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
+
+<component-specification class="net.sf.oreka.tapestry.TablePaging"
+ allow-informal-parameters="no">
+
+ <parameter name="tableState" type="net.sf.oreka.tapestry.TableState" direction="auto" required="yes"/>
+
+ <property-specification name="sliderPosition" type="java.lang.Integer"/>
+
+ <context-asset name="first" path="/images/icon_pagefirst.gif"/>
+ <context-asset name="last" path="/images/icon_pagelast.gif"/>
+ <context-asset name="previous" path="/images/icon_pageprev.gif"/>
+ <context-asset name="next" path="/images/icon_pagenext.gif"/>
+</component-specification> \ No newline at end of file
diff --git a/orkweb/src/net/sf/oreka/tapestry/TablePaging.properties b/orkweb/src/net/sf/oreka/tapestry/TablePaging.properties
new file mode 100644
index 0000000..428a861
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TablePaging.properties
@@ -0,0 +1,4 @@
+nextPage=>
+previousPage=<
+lastPage=>>
+firstPage=<<
diff --git a/orkweb/src/net/sf/oreka/tapestry/TableState.java b/orkweb/src/net/sf/oreka/tapestry/TableState.java
new file mode 100644
index 0000000..0a1c44c
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/TableState.java
@@ -0,0 +1,143 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+/**
+ *
+ */
+package net.sf.oreka.tapestry;
+
+import org.apache.log4j.Logger;
+
+public class TableState {
+
+ static Logger logger = Logger.getLogger(TableState.class);
+
+ public static int DEFAULT_RESULTS_PER_PAGE = 10;
+
+ private int NumResults;
+ private int ResultsPerPage;
+ private int CurrentOffset;
+ private int sliderPosition;
+ private String OrderBy = new String();
+ private boolean Ascending = false;
+
+ /**
+ * @return Returns the ascending.
+ */
+ public boolean isAscending() {
+ return Ascending;
+ }
+
+
+ /**
+ * @param ascending The ascending to set.
+ */
+ public void setAscending(boolean ascending) {
+ Ascending = ascending;
+ }
+
+ /**
+ * @return Returns the orderBy.
+ */
+ public String getOrderBy() {
+ return OrderBy;
+ }
+
+
+ /**
+ * @param orderBy The orderBy to set.
+ */
+ public void setOrderBy(String orderBy) {
+ OrderBy = orderBy;
+ }
+
+
+ /**
+ *
+ */
+ public TableState() {
+ ResultsPerPage = DEFAULT_RESULTS_PER_PAGE;
+ }
+
+ /**
+ * @return Returns the currentOffset.
+ */
+ public int getCurrentOffset() {
+ return CurrentOffset;
+ }
+
+
+ /**
+ * @param currentOffset The currentOffset to set.
+ */
+ public void setCurrentOffset(int currentOffset) {
+ CurrentOffset = currentOffset;
+ }
+
+
+ /**
+ * @return Returns the numResults.
+ */
+ public int getNumResults() {
+ return NumResults;
+ }
+
+
+ /**
+ * @param numResults The numResults to set.
+ */
+ public void setNumResults(int numResults) {
+ if (NumResults != numResults){
+ NumResults = numResults;
+ CurrentOffset = 0; // reset the offset if different resultset
+ }
+ }
+
+
+ /**
+ * @return Returns the resultsPerPage.
+ */
+ public int getResultsPerPage() {
+ return ResultsPerPage;
+ }
+
+
+ /**
+ * @param resultsPerPage The resultsPerPage to set.
+ */
+ public void setResultsPerPage(int resultsPerPage) {
+ ResultsPerPage = resultsPerPage;
+ }
+
+ public int getNumPages() {
+ double numPages = (double)getNumResults() / getResultsPerPage();
+ return (int)java.lang.Math.ceil(numPages);
+ }
+
+ public int getCurrentPage() {
+ return (getCurrentOffset() / getResultsPerPage())+1;
+ }
+
+
+ public int getSliderPosition() {
+ return sliderPosition;
+ }
+
+
+
+ public void setSliderPosition(int sliderPosition) {
+ this.sliderPosition = sliderPosition;
+ }
+
+
+}
diff --git a/orkweb/src/net/sf/oreka/tapestry/my.library b/orkweb/src/net/sf/oreka/tapestry/my.library
new file mode 100644
index 0000000..daadbfa
--- /dev/null
+++ b/orkweb/src/net/sf/oreka/tapestry/my.library
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library-specification
+ PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
+ "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
+<!-- generated by Spindle, http://spindle.sourceforge.net -->
+
+
+<library-specification>
+
+ <description>Project specific components</description>
+
+ <library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>
+</library-specification>