You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by sm...@apache.org on 2012/01/19 01:51:42 UTC

svn commit: r1233143 [39/47] - in /pivot/site/trunk/deploy: ./ 2.0.1/ 2.0.1/docs/ 2.0.1/docs/api/ demos/ tutorials/

Modified: pivot/site/trunk/deploy/tutorials/stock-tracker.web-queries.html
URL: http://svn.apache.org/viewvc/pivot/site/trunk/deploy/tutorials/stock-tracker.web-queries.html?rev=1233143&r1=1233142&r2=1233143&view=diff
==============================================================================
--- pivot/site/trunk/deploy/tutorials/stock-tracker.web-queries.html (original)
+++ pivot/site/trunk/deploy/tutorials/stock-tracker.web-queries.html Thu Jan 19 00:51:39 2012
@@ -1,4 +1,4 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <!--
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
@@ -14,466 +14,468 @@ distributed under the License is distrib
 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.
---><html xmlns="http://www.w3.org/1999/xhtml"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type" /><title>Web Queries | Apache Pivot</title><link xmlns="" type="text/css" rel="stylesheet" href="/styles/pivot.css"><script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
-                var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-                document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-                </script><script type="text/javascript">
-                try {
-                var pageTracker = _gat._getTracker("UA-7977275-3");
-                pageTracker._trackPageview();
-                } catch(err) {}</script></head><body><div xmlns="" id="wrapper"><div id="main"><div id="header"><div class="logo"><a href="/index.html"><img title="Apache Pivot Homepage" alt="Apache Pivot" src="/images/logo.png"></a></div><div class="tagline"><img style="visibility:hidden" alt="Rich Internet Applications in Java" src="/images/tagline.png"></div><ul class="navi"><li><a href="/demos/">Demos</a></li><li><a href="/download.cgi#2.0">Download</a></li><li><a href="/tutorials/">Tutorial</a></li><li><a href="/get-involved.html">Get Involved</a></li><li><a href="/about.html">About</a></li></ul></div><div class="group" id="contentBase"><h1>Web Queries</h1><ul class="naviLeft"><li><a href="/tutorials/sample-application.html">Sample Application</a></li><li><a href="/tutorials/platform-overview.html">Platform Overview</a></li><li><a href="/tutorials/hello-world.html">Hello, World!</a></li><li><a href="/tutorials/hello-bxml.html">Hello, BXML!</a></li><li><a href="/tutorial
 s/component-and-container.html">Component &amp; Container</a></li><li><a href="/tutorials/labels-and-image-views.html">Labels &amp; Image Views</a></li><li><a href="/tutorials/svg-images.html">SVG Images</a></li><li><a href="/tutorials/buttons.html">Buttons</a></li><li><a href="/tutorials/push-buttons.html">Push Buttons</a></li><li><a href="/tutorials/toggle-buttons.html">Toggle Buttons</a></li><li><a href="/tutorials/radio-buttons.html">Radio Buttons</a></li><li><a href="/tutorials/checkboxes.html">Checkboxes</a></li><li><a href="/tutorials/link-buttons.html">Link Buttons</a></li><li><a href="/tutorials/lists.html">Lists</a></li><li><a href="/tutorials/list-buttons.html">List Buttons</a></li><li><a href="/tutorials/repeatable-list-buttons.html">Repeatable List Buttons</a></li><li><a href="/tutorials/text.html">Text</a></li><li><a href="/tutorials/suggestion-popups.html">Suggestion Popups</a></li><li><a href="/tutorials/text-areas.html">Text Areas</a></li><li><a href="/tutor
 ials/separators.html">Separators</a></li><li><a href="/tutorials/layout-containers.html">Layout Containers</a></li><li><a href="/tutorials/flow-panes.html">Flow Panes</a></li><li><a href="/tutorials/box-panes.html">Box Panes</a></li><li><a href="/tutorials/grid-panes.html">Grid Panes</a></li><li><a href="/tutorials/table-panes.html">Table Panes</a></li><li><a href="/tutorials/borders.html">Borders</a></li><li><a href="/tutorials/stack-panes.html">Stack Panes</a></li><li><a href="/tutorials/split-panes.html">Split Panes</a></li><li><a href="/tutorials/forms.html">Forms</a></li><li><a href="/tutorials/panels.html">Panels</a></li><li><a href="/tutorials/navigation-containers.html">Navigation Containers</a></li><li><a href="/tutorials/card-panes.html">Card Panes</a></li><li><a href="/tutorials/tab-panes.html">Tab Panes</a></li><li><a href="/tutorials/accordions.html">Accordions</a></li><li><a href="/tutorials/expanders.html">Expanders</a></li><li><a href="/tutorials/rollups.html
 ">Rollups</a></li><li><a href="/tutorials/viewports.html">Viewports</a></li><li><a href="/tutorials/scroll-panes.html">Scroll Panes</a></li><li><a href="/tutorials/panoramas.html">Panoramas</a></li><li><a href="/tutorials/progress-indicators.html">Progress Indicators</a></li><li><a href="/tutorials/meters.html">Meters</a></li><li><a href="/tutorials/activity-indicators.html">Activity Indicators</a></li><li><a href="/tutorials/bounded-range-components.html">Bounded Range Components</a></li><li><a href="/tutorials/sliders.html">Sliders</a></li><li><a href="/tutorials/scroll-bars.html">Scroll Bars</a></li><li><a href="/tutorials/spinners.html">Spinners</a></li><li><a href="/tutorials/calendars.html">Calendars</a></li><li><a href="/tutorials/menus.html">Menus</a></li><li><a href="/tutorials/context-menus.html">Context Menus</a></li><li><a href="/tutorials/menu-bars.html">Menu Bars</a></li><li><a href="/tutorials/menu-buttons.html">Menu Buttons</a></li><li><a href="/tutorials/col
 or-choosers.html">Color Choosers</a></li><li><a href="/tutorials/table-views.html">Table Views</a></li><li><a href="/tutorials/table-views.json.html">JSON-based TableView</a></li><li><a href="/tutorials/table-views.custom.html">Custom TableView</a></li><li><a href="/tutorials/tree-views.html">Tree Views</a></li><li><a href="/tutorials/file-browsing.html">File Browsing</a></li><li><a href="/tutorials/windows.html">Windows</a></li><li><a href="/tutorials/clipboard.html">Clipboard</a></li><li><a href="/tutorials/drag-and-drop.html">Drag and Drop</a></li><li><a href="/tutorials/effects.html">Effects</a></li><li><a href="/tutorials/effects.transitions.html">Transitions</a></li><li><a href="/tutorials/data-binding.html">Data Binding</a></li><li><a href="/tutorials/property-binding.html">Property Binding</a></li><li><a href="/tutorials/localization.html">Localization</a></li><li><a href="/tutorials/background-tasks.html">Background Tasks</a></li><li><a href="/tutorials/web-queries.
 html">Web Queries</a></li><li><a href="/tutorials/query-servlet.html">QueryServlet</a></li><li><a href="/tutorials/scripting.html">Scripting</a></li><li><a href="/tutorials/summary.html">Summary</a></li><li><a href="/tutorials/stock-tracker.html">The "Stock Tracker" Application</a></li><li><a href="/tutorials/stock-tracker.ui.html">UI Markup Using BXML</a></li><li><a href="/tutorials/stock-tracker.events.html">Event Handling</a></li><li><a href="/tutorials/stock-tracker.web-queries.html">Web Queries</a></li><li><a href="/tutorials/stock-tracker.data-binding.html">Data Binding</a></li><li><a href="/tutorials/stock-tracker.localization.html">Localization</a></li><li><a href="/tutorials/bxml-primer.html">BXML Primer</a></li></ul><div class="content"><style type="text/css">
-            applet {
-                border: 1px solid #999999;
-            }
-        </style><!--NOTE: Syntax highlighting script is LGPL--><script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript"></script><script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js" type="text/javascript"></script><script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js" type="text/javascript"></script><script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js" type="text/javascript"></script><link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css"><link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css"><script type="text/javascript">
-            SyntaxHighlighter.all();
-        </script><div class="section">
-        <p>
-            "Web queries" are Pivot's native means of communicating with remote data services. They
-            are designed primarily to facilitate interaction with JSON-based REST services.
-            However, they are sufficiently generic to support communication with any type of
-            HTTP-based service, using any data format.
-        </p>
-
-        <p>
-            For example, the data presented by the Stock Tracker application is retrieved from
-            Yahoo! Finance as a comma-separated value (CSV) file:
-        </p>
-
-        <p>
-            <tt>"AAPL","APPLE INC",171.06,169.59,172.17,166.00,+2.88,12995693</tt><br>
-            <tt>"AMZN","AMAZON.COM INC",72.54,72.35,73.83,70.52,+1.10,2748930</tt><br>
-            <tt>"EBAY","EBAY INC",27.09,27.35,27.44,27.04,-0.02,3426369</tt><br>
-        </p>
-
-        <p>
-            This data is returned by submitting an HTTP GET request to
-            <a href="http://download.finance.yahoo.com/d/quotes.csv/">http://download.finance.yahoo.com/d/quotes.csv/</a>
-            with an appropriate set of query string arguments. For example, the Stock Tracker
-            application passes the following arguments to the service URL:
-        </p>
-
-        <ul>
-            <li>
-                <b>s</b> - A comma-separated list of stock symbols representing the quotes to
-                retrieve.
-            </li>
-            <li>
-                <b>f</b> - the requested format for the resulting CSV file; this is a string of
-                characters representing the various data fields returned by the query. The format
-                used by the Stock Tracker application is "snl1ohgc1v":
-                <ul>
-                    <li><i>s</i> - symbol</li>
-                    <li><i>n</i> - company name</li>
-                    <li><i>l1</i> - most recent value</li>
-                    <li><i>o</i> - opening value</li>
-                    <li><i>h</i> - high value</li>
-                    <li><i>g</i> - low value</li>
-                    <li><i>c1</i> - change percentage</li>
-                    <li><i>v</i> - volume</li>
-                </ul>
-            </li>
-        </ul>
-
-        <p>
-            Note that this query actually returns more data than can be displayed in the table
-            view. The other data fields are used by the quote detail view, which is discussed in
-            more detail in the <a href="stock-tracker.data-binding.html">data binding</a> section.
-        </p>
-
-        <h2>Constructing the Web Query</h2>
-
-        <p>
-            In order to display the stock quotes to the user, Stock Tracker must execute a web
-            query to retrieve the data from the Yahoo! Finance web service and then populate the
-            stock quote table view with the results of the query. The query is executed in the
-            <tt>refreshTable()</tt> method, and the table is populated by a callback handler
-            implemented as an anonymous inner class defined in this method. This code is defined in
-            the <tt>StockTracker</tt> class.
-        </p>
-
-        <p>
-            First, the web query is created:
-        </p>
-
-        <pre class="brush:java">
-
-            getQuery = new GetQuery(SERVICE_HOSTNAME, SERVICE_PATH);
-
-        </pre>
-
-        <p>
-            Then, the value of the "s" parameter is constructed by joining the values in the symbol
-            list with commas, and the query arguments are applied:
-        </p>
-
-        <pre class="brush:java">
-
-            StringBuilder symbolsParameterBuilder = new StringBuilder();
-            for (int i = 0, n = symbols.getLength(); i &lt; n; i++) {
-                if (i &gt; 0) {
-                    symbolsParameterBuilder.append(",");
-                }
-
-                symbolsParameterBuilder.append(symbols.get(i));
-            }
-
-            // Format:
-            // s - symbol
-            // n - company name
-            // l1 - most recent value
-            // o - opening value
-            // h - high value
-            // g - low value
-            // c1 - change percentage
-            // v - volume
-            String symbolsParameter = symbolsParameterBuilder.toString();
-            getQuery.getParameters().put("s", symbolsParameter);
-            getQuery.getParameters().put("f", "snl1ohgc1v");
-
-        </pre>
-
-        <p>
-            The resulting query URL would be similar to:
-        </p>
-
-        <p style="padding-left:24px">
-            <a href="http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&f=snl1ohgc1v">http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&amp;f=snl1ohgc1v</a>
-        </p>
-
-        <p>
-            Next, an instance of CSVSerializer is created and configured:
-        </p>
-
-        <pre class="brush:java">
-
-            CSVSerializer quoteSerializer = new CSVSerializer(StockQuote.class);
-            quoteSerializer.setKeys("symbol",
-                "companyName",
-                "value",
-                "openingValue",
-                "highValue",
-                "lowValue",
-                "change",
-                "volume");
-
-        </pre>
-
-        <p>
-            By default, the <tt>GetQuery</tt> class uses an instance of
-            <tt>org.apache.pivot.core.serialization.JSONSerializer</tt> to deserialize data
-            returned by a GET request. However, the quote data from Yahoo! Finance is returned as
-            a CSV file; <tt>CSVSerializer</tt> is an implementation of the
-            <tt>org.apache.pivot.core.serialization.Serializer</tt> interface that parses a CSV
-            data stream into a sequence of name/value pairs.
-        </p>
-
-        <p>
-            By default, <tt>CSVSerializer</tt> will create an instance of
-            <tt>org.apache.pivot.collections.HashMap&lt;String, Object&gt;</tt> for each row it
-            encounters in the CSV stream. However, a caller can specify the name of a different
-            class as a constructor argument to <tt>CSVSerializer</tt>. This avoids the performance
-            penalty of traversing the data twice: once to read it from the CSV stream and again to
-            convert it to the appropriate type.
-        </p>
-
-        <p>
-            If the item class implements the <tt>org.apache.pivot.collections.Dictionary</tt>
-            interface, the parsed values are <tt>put()</tt> directly into the item instance;
-            otherwise, the item is wrapped in a <tt>org.apache.pivot.beans.BeanAdapter</tt> into
-            which the values are <tt>put()</tt> (<tt>BeanAdapter</tt> is a handy class that allows
-            a caller to treat a Java bean object as if it were a dictionary).
-        </p>
-
-        <p>
-            Stock Tracker uses the <tt>StockQuote</tt> class to represent the rows in the CSV file:
-        </p>
-
-        <pre class="brush:java">
-
-            public class StockQuote {
-                private String symbol = null;
-                private String companyName = null;
-                private float value = 0;
-                private float openingValue = 0;
-                private float highValue = 0;
-                private float lowValue = 0;
-                private float change = 0;
-                private float volume = 0;
-
-                public String getSymbol() {
-                    return symbol;
-                }
-
-                public void setSymbol(String symbol) {
-                    this.symbol = symbol;
-                }
-
-                public String getCompanyName() {
-                    return companyName;
-                }
-
-                public void setCompanyName(String companyName) {
-                    this.companyName = companyName;
-                }
-
-                public float getValue() {
-                    return value;
-                }
-
-                public void setValue(float value) {
-                    this.value = value;
-                }
-
-                public void setValue(String value) {
-                    try {
-                        setValue(Float.parseFloat(value));
-                    } catch(NumberFormatException exception) {
-                        setValue(Float.NaN);
-                    }
-                }
-
-                public float getOpeningValue() {
-                    return openingValue;
-                }
-
-                public void setOpeningValue(float openingValue) {
-                    this.openingValue = openingValue;
-                }
-
-                public void setOpeningValue(String openingValue) {
-                    try {
-                        setOpeningValue(Float.parseFloat(openingValue));
-                    } catch(NumberFormatException exception) {
-                        setOpeningValue(Float.NaN);
-                    }
-                }
-
-                public float getHighValue() {
-                    return highValue;
-                }
-
-                public void setHighValue(float highValue) {
-                    this.highValue = highValue;
-                }
-
-                public void setHighValue(String highValue) {
-                    try {
-                        setHighValue(Float.parseFloat(highValue));
-                    } catch(NumberFormatException exception) {
-                        setHighValue(Float.NaN);
-                    }
-                }
-
-                public float getLowValue() {
-                    return lowValue;
-                }
-
-                public void setLowValue(float lowValue) {
-                    this.lowValue = lowValue;
-                }
-
-                public void setLowValue(String lowValue) {
-                    try {
-                        setLowValue(Float.parseFloat(lowValue));
-                    } catch(NumberFormatException exception) {
-                        setLowValue(Float.NaN);
-                    }
-                }
-
-                public float getChange() {
-                    return change;
-                }
-
-                public void setChange(float change) {
-                    this.change = change;
-                }
-
-                public void setChange(String change) {
-                    try {
-                        setChange(Float.parseFloat(change));
-                    } catch(NumberFormatException exception) {
-                        setChange(Float.NaN);
-                    }
-                }
-
-                public float getVolume() {
-                    return volume;
-                }
-
-                public void setVolume(float volume) {
-                    this.volume = volume;
-                }
-
-                public void setVolume(String volume) {
-                    try {
-                        setVolume(Float.parseFloat(volume));
-                    } catch(NumberFormatException exception) {
-                        setVolume(Float.NaN);
-                    }
-                }
-            }
-
-        </pre>
-
-        <p>
-            The cell renderers assigned to the columns in the BXML file ensure that the data
-            represented by this class is formatted and presented correctly.
-        </p>
-
-        <p>
-            Finally, the query is executed:
-        </p>
-
-        <pre class="brush:java">
-
-            getQuery.setSerializer(quoteSerializer);
-
-            getQuery.execute(new TaskAdapter&lt;Object&gt;(new TaskListener&lt;Object&gt;() {
-            ...
-            }
-
-        </pre>
-
-        <p>
-            The argument passed to the <tt>execute()</tt> method is a <tt>TaskAdapter</tt> wrapped
-            around an anonymous inner class implementation of <tt>TaskListener&lt;Object&gt;</tt>.
-            <tt>TaskListener</tt> is an interface defined in the <tt>org.apache.pivot.util.concurrent</tt>
-            package and serves as a callback handler for asynchronous operations implemented by the
-            <tt>org.apache.pivot.util.concurrent.Task</tt> class, of which <tt>GetQuery</tt> is a subclass.
-            <tt>TaskAdapter</tt> is defined in the <tt>pivot.wtk</tt> package and ensures that the
-            callback occurs on the UI thread (otherwise, the listener is called in the context of
-            the background thread, which can produce non-deterministic results).
-        </p>
-
-        <p>
-            <tt>TaskListener</tt> defines two methods:
-        </p>
-
-        <p>
-            <tt>public void taskExecuted(Task&lt;V&gt; task);</tt><br>
-            <tt>public void executeFailed(Task&lt;V&gt; task);</tt><br>
-        </p>
-
-        <p>
-            The template parameter <tt>V</tt> is defined by the <tt>Task</tt> class and represents
-            the (optional) return value of the operation. The first method is called if the task
-            completes successfully, and the second is called if the task failed for any reason.
-        </p>
-
-        <p>
-            StockTracker's success handler is defined as follows:
-        </p>
-
-        <pre class="brush:java">
-
-                @Override
-                public void taskExecuted(Task&lt;Object&gt; task) {
-                    if (task == getQuery) {
-                        List&lt;Object&gt; quotes = (List&lt;Object&gt;)task.getResult();
-
-                        // Preserve any existing sort and selection
-                        Sequence&lt;?&gt; selectedStocks = stocksTableView.getSelectedRows();
-
-                        List&lt;Object&gt; tableData = (List&lt;Object&gt;)stocksTableView.getTableData();
-                        Comparator&lt;Object&gt; comparator = tableData.getComparator();
-                        quotes.setComparator(comparator);
-
-                        stocksTableView.setTableData(quotes);
-
-                        if (selectedStocks.getLength() &gt; 0) {
-                            // Select current indexes of selected stocks
-                            for (int i = 0, n = selectedStocks.getLength(); i &lt; n; i++) {
-                                Object selectedStock = selectedStocks.get(i);
-
-                                int index = 0;
-                                for (Object stock : stocksTableView.getTableData()) {
-                                    String symbol = JSON.get(stock, "symbol");
-                                    String selectedSymbol = JSON.get(selectedStock, "symbol");
-
-                                    if (symbol.equals(selectedSymbol)) {
-                                        stocksTableView.addSelectedIndex(index);
-                                        break;
-                                    }
-
-                                    index++;
-                                }
-                            }
-                        } else {
-                            if (quotes.getLength() &gt; 0) {
-                                stocksTableView.setSelectedIndex(0);
-                            }
-                        }
-
-                        refreshDetail();
-
-                        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
-                            DateFormat.MEDIUM, Locale.getDefault());
-                        lastUpdateLabel.setText(dateFormat.format(new Date()));
-
-                        getQuery = null;
-                    }
-                }
-            }
-
-        </pre>
-
-        <p>
-            If the source of the event is the currently executing task, the handler does the
-            following:
-        </p>
-
-        <ul>
-            <li>
-                <p>
-                    Caches the current sort and selection state of the quote table view
-                </p>
-            </li>
-            <li>
-                <p>
-                    Gets the result of the query and casts it to the appropriate type
-                    (<tt>List&lt;Object&gt;</tt>)
-                </p>
-            </li>
-            <li>
-                <p>
-                    Sets the list as the model data for the table view
-                </p>
-            </li>
-            <li>
-                <p>
-                    Restores any selection state (which would have been lost when the model data
-                    was reset)
-                </p>
-            </li>
-            <li>
-                <p>
-                    Updates the value of the "last updated" label to reflect the current time, in
-                    a manner appropriate for the current locale
-                </p>
-            </li>
-        </ul>
-
-        <p>
-            In the case of a failure, the handler simply logs the exception to the console:
-        </p>
-
-        <pre class="brush:java">
-
-            @Override
-            public void executeFailed(Task&lt;Object&gt; task) {
-                if (task == getQuery) {
-                    System.err.println(task.getFault());
-                    getQuery = null;
-                }
-            }
-
-        </pre>
-
-        <p>
-            This example demonstrates the use of <tt>GetQuery</tt> only, but Pivot also provides
-            support for HTTP POST, PUT, and DELETE operations using the <tt>PostQuery</tt>,
-            <tt>PutQuery</tt>, and <tt>DeleteQuery</tt> classes, respectively. This makes it very
-            easy to built a complete REST client using Pivot.
-        </p>
-    </div><p>Next: <a href="stock-tracker.data-binding.html">Data Binding</a></p></div></div></div><div class="group" id="footer"><div class="footerLogo">Copyright (c) 1999-2011<br>The Apache Software Foundation.</div><div class="footerLinks"><ul class="footerMenuGr"><li><strong>Demos</strong><ul><li><a href="/demos/kitchen-sink.html" target="_new">"Kitchen Sink"</a></li><li><a href="/demos/component-explorer.html" target="_new">Component Explorer</a></li><li><a href="http://ixnay.biz/pivot-jfree-demos/charts_demo.html" target="_new">Charting</a></li><li><a href="/demos/">More Demos</a></li></ul></li><li><strong>Documentation</strong><ul><li><a href="/getting-started.html">Getting Started</a></li><li><a href="/tutorials/">Tutorial</a></li><li><a href="/faq.html">FAQ</a></li><li><a href="/2.0/docs/api/">Javadoc (2.0)</a></li></ul></li><li><strong>Get Involved</strong><ul><li><a href="/svn.html">SVN Repositories</a></li><li><a href="/lists.html">Mailing Lists</a></li><li><a hr
 ef="http://issues.apache.org/jira/browse/PIVOT">Bug Database</a></li><li><a href="http://cwiki.apache.org/PIVOT/">Wiki</a></li></ul></li><li><strong>Related</strong><ul><li><a href="http://code.google.com/p/pivot-jfree/">JFreeChart Provider</a></li></ul></li><li><strong>About</strong><ul><li><a href="/who-we-are.html">Who We Are</a></li><li><a href="/contact.html">Contact</a></li><li><a href="/news.html">News</a></li><li><a href="/legal.html">Legal/License</a></li></ul></li></ul></div></div></div></body></html>
\ No newline at end of file
+--><html xmlns="http://www.w3.org/1999/xhtml"><head><META http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Web Queries | Apache Pivot</title><link href="/styles/pivot.css" rel="stylesheet" type="text/css"><script type="text/javascript">
+                var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+                document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+                </script><script type="text/javascript">
+                try {
+                var pageTracker = _gat._getTracker("UA-7977275-3");
+                pageTracker._trackPageview();
+                } catch(err) {}</script></head><body><div id="wrapper"><div id="main"><div id="header"><div xmlns="" class="logo"><a href="/index.html"><img src="/images/logo.png" alt="Apache Pivot" title="Apache Pivot Homepage"></a></div><div class="tagline"><img src="/images/tagline.png" alt="Rich Internet Applications in Java" style="visibility:hidden"></div><ul class="navi"><li><a href="/demos/">Demos</a></li><li><a href="/download.cgi#2.0.1">Download</a></li><li><a href="/tutorials/">Tutorial</a></li><li><a href="/get-involved.html">Get Involved</a></li><li><a href="/about.html">About</a></li></ul></div><div id="contentBase" class="group"><h1>Web Queries</h1><ul class="naviLeft"><li><a href="/tutorials/sample-application.html">Sample Application</a></li><li><a href="/tutorials/platform-overview.html">Platform Overview</a></li><li><a href="/tutorials/hello-world.html">Hello, World!</a></li><li><a href="/tutorials/hello-bxml.html">Hello, BXML!</a></li><li><a href="/tutori
 als/component-and-container.html">Component &amp; Container</a></li><li><a href="/tutorials/labels-and-image-views.html">Labels &amp; Image Views</a></li><li><a href="/tutorials/svg-images.html">SVG Images</a></li><li><a href="/tutorials/buttons.html">Buttons</a></li><li><a href="/tutorials/push-buttons.html">Push Buttons</a></li><li><a href="/tutorials/toggle-buttons.html">Toggle Buttons</a></li><li><a href="/tutorials/radio-buttons.html">Radio Buttons</a></li><li><a href="/tutorials/checkboxes.html">Checkboxes</a></li><li><a href="/tutorials/link-buttons.html">Link Buttons</a></li><li><a href="/tutorials/lists.html">Lists</a></li><li><a href="/tutorials/list-buttons.html">List Buttons</a></li><li><a href="/tutorials/repeatable-list-buttons.html">Repeatable List Buttons</a></li><li><a href="/tutorials/text.html">Text</a></li><li><a href="/tutorials/suggestion-popups.html">Suggestion Popups</a></li><li><a href="/tutorials/text-areas.html">Text Areas</a></li><li><a href="/tut
 orials/separators.html">Separators</a></li><li><a href="/tutorials/layout-containers.html">Layout Containers</a></li><li><a href="/tutorials/flow-panes.html">Flow Panes</a></li><li><a href="/tutorials/box-panes.html">Box Panes</a></li><li><a href="/tutorials/fill-panes.html">Fill Panes</a></li><li><a href="/tutorials/grid-panes.html">Grid Panes</a></li><li><a href="/tutorials/table-panes.html">Table Panes</a></li><li><a href="/tutorials/borders.html">Borders</a></li><li><a href="/tutorials/stack-panes.html">Stack Panes</a></li><li><a href="/tutorials/split-panes.html">Split Panes</a></li><li><a href="/tutorials/forms.html">Forms</a></li><li><a href="/tutorials/panels.html">Panels</a></li><li><a href="/tutorials/navigation-containers.html">Navigation Containers</a></li><li><a href="/tutorials/card-panes.html">Card Panes</a></li><li><a href="/tutorials/tab-panes.html">Tab Panes</a></li><li><a href="/tutorials/accordions.html">Accordions</a></li><li><a href="/tutorials/expander
 s.html">Expanders</a></li><li><a href="/tutorials/rollups.html">Rollups</a></li><li><a href="/tutorials/viewports.html">Viewports</a></li><li><a href="/tutorials/scroll-panes.html">Scroll Panes</a></li><li><a href="/tutorials/panoramas.html">Panoramas</a></li><li><a href="/tutorials/progress-indicators.html">Progress Indicators</a></li><li><a href="/tutorials/meters.html">Meters</a></li><li><a href="/tutorials/activity-indicators.html">Activity Indicators</a></li><li><a href="/tutorials/bounded-range-components.html">Bounded Range Components</a></li><li><a href="/tutorials/sliders.html">Sliders</a></li><li><a href="/tutorials/scroll-bars.html">Scroll Bars</a></li><li><a href="/tutorials/spinners.html">Spinners</a></li><li><a href="/tutorials/calendars.html">Calendars</a></li><li><a href="/tutorials/menus.html">Menus</a></li><li><a href="/tutorials/context-menus.html">Context Menus</a></li><li><a href="/tutorials/menu-bars.html">Menu Bars</a></li><li><a href="/tutorials/menu-
 buttons.html">Menu Buttons</a></li><li><a href="/tutorials/color-choosers.html">Color Choosers</a></li><li><a href="/tutorials/table-views.html">Table Views</a></li><li><a href="/tutorials/table-views.json.html">JSON-based TableView</a></li><li><a href="/tutorials/table-views.custom.html">Custom TableView</a></li><li><a href="/tutorials/tree-views.html">Tree Views</a></li><li><a href="/tutorials/file-browsing.html">File Browsing</a></li><li><a href="/tutorials/windows.html">Windows</a></li><li><a href="/tutorials/clipboard.html">Clipboard</a></li><li><a href="/tutorials/drag-and-drop.html">Drag and Drop</a></li><li><a href="/tutorials/effects.html">Effects</a></li><li><a href="/tutorials/effects.transitions.html">Transitions</a></li><li><a href="/tutorials/data-binding.html">Data Binding</a></li><li><a href="/tutorials/property-binding.html">Property Binding</a></li><li><a href="/tutorials/localization.html">Localization</a></li><li><a href="/tutorials/background-tasks.html"
 >Background Tasks</a></li><li><a href="/tutorials/web-queries.html">Web Queries</a></li><li><a href="/tutorials/query-servlet.html">QueryServlet</a></li><li><a href="/tutorials/scripting.html">Scripting</a></li><li><a href="/tutorials/summary.html">Summary</a></li><li><a href="/tutorials/stock-tracker.html">The "Stock Tracker" Application</a></li><li><a href="/tutorials/stock-tracker.ui.html">UI Markup Using BXML</a></li><li><a href="/tutorials/stock-tracker.events.html">Event Handling</a></li><li><a href="/tutorials/stock-tracker.web-queries.html">Web Queries</a></li><li><a href="/tutorials/stock-tracker.data-binding.html">Data Binding</a></li><li><a href="/tutorials/stock-tracker.localization.html">Localization</a></li><li><a href="/tutorials/bxml-primer.html">BXML Primer</a></li></ul><div class="content"><style type="text/css">
+            applet {
+                border: 1px solid #999999;
+            }
+        </style><!--NOTE: Syntax highlighting script is LGPL--><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js"></script><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js"></script><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js"></script><link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"><link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"><script type="text/javascript">
+            SyntaxHighlighter.all();
+        </script><div class="section">
+        <p>
+            "Web queries" are Pivot's native means of communicating with remote data services. They
+            are designed primarily to facilitate interaction with JSON-based REST services.
+            However, they are sufficiently generic to support communication with any type of
+            HTTP-based service, using any data format.
+        </p>
+
+        <p>
+            For example, the data presented by the Stock Tracker application is retrieved from
+            Yahoo! Finance as a comma-separated value (CSV) file:
+        </p>
+
+        <p>
+            <tt>"AAPL","APPLE INC",171.06,169.59,172.17,166.00,+2.88,12995693</tt><br>
+            <tt>"AMZN","AMAZON.COM INC",72.54,72.35,73.83,70.52,+1.10,2748930</tt><br>
+            <tt>"EBAY","EBAY INC",27.09,27.35,27.44,27.04,-0.02,3426369</tt><br>
+        </p>
+
+        <p>
+            This data is returned by submitting an HTTP GET request to
+            <a href="http://download.finance.yahoo.com/d/quotes.csv/">http://download.finance.yahoo.com/d/quotes.csv/</a>
+            with an appropriate set of query string arguments. For example, the Stock Tracker
+            application passes the following arguments to the service URL:
+        </p>
+
+        <ul>
+            <li>
+                <b>s</b> - A comma-separated list of stock symbols representing the quotes to
+                retrieve.
+            </li>
+            <li>
+                <b>f</b> - the requested format for the resulting CSV file; this is a string of
+                characters representing the various data fields returned by the query. The format
+                used by the Stock Tracker application is "snl1ohgc1v":
+                <ul>
+                    <li><i>s</i> - symbol</li>
+                    <li><i>n</i> - company name</li>
+                    <li><i>l1</i> - most recent value</li>
+                    <li><i>o</i> - opening value</li>
+                    <li><i>h</i> - high value</li>
+                    <li><i>g</i> - low value</li>
+                    <li><i>c1</i> - change percentage</li>
+                    <li><i>v</i> - volume</li>
+                </ul>
+            </li>
+        </ul>
+
+        <p>
+            Note that this query actually returns more data than can be displayed in the table
+            view. The other data fields are used by the quote detail view, which is discussed in
+            more detail in the <a href="stock-tracker.data-binding.html">data binding</a> section.
+        </p>
+
+        <h3>Constructing the Web Query</h3>
+
+        <p>
+            In order to display the stock quotes to the user, Stock Tracker must execute a web
+            query to retrieve the data from the Yahoo! Finance web service and then populate the
+            stock quote table view with the results of the query. The query is executed in the
+            <tt>refreshTable()</tt> method, and the table is populated by a callback handler
+            implemented as an anonymous inner class defined in this method. This code is defined in
+            the <tt>StockTracker</tt> class.
+        </p>
+
+        <p>
+            First, the web query is created:
+        </p>
+
+        <pre class="brush:java">
+            
+            getQuery = new GetQuery(SERVICE_HOSTNAME, SERVICE_PATH);
+            
+        </pre>
+
+        <p>
+            Then, the value of the "s" parameter is constructed by joining the values in the symbol
+            list with commas, and the query arguments are applied:
+        </p>
+
+        <pre class="brush:java">
+            
+            StringBuilder symbolsParameterBuilder = new StringBuilder();
+            for (int i = 0, n = symbols.getLength(); i &lt; n; i++) {
+                if (i &gt; 0) {
+                    symbolsParameterBuilder.append(",");
+                }
+
+                symbolsParameterBuilder.append(symbols.get(i));
+            }
+
+            // Format:
+            // s - symbol
+            // n - company name
+            // l1 - most recent value
+            // o - opening value
+            // h - high value
+            // g - low value
+            // c1 - change percentage
+            // v - volume
+            String symbolsParameter = symbolsParameterBuilder.toString();
+            getQuery.getParameters().put("s", symbolsParameter);
+            getQuery.getParameters().put("f", "snl1ohgc1v");
+            
+        </pre>
+
+        <p>
+            The resulting query URL would be similar to:
+        </p>
+
+        <p style="padding-left:24px">
+            <a href="http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&amp;f=snl1ohgc1v">http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&amp;f=snl1ohgc1v</a>
+        </p>
+
+        <p>
+            Next, an instance of CSVSerializer is created and configured:
+        </p>
+
+        <pre class="brush:java">
+            
+            CSVSerializer quoteSerializer = new CSVSerializer(StockQuote.class);
+            quoteSerializer.setKeys("symbol",
+                "companyName",
+                "value",
+                "openingValue",
+                "highValue",
+                "lowValue",
+                "change",
+                "volume");
+            
+        </pre>
+
+        <p>
+            By default, the <tt>GetQuery</tt> class uses an instance of
+            <tt>org.apache.pivot.core.serialization.JSONSerializer</tt> to deserialize data
+            returned by a GET request. However, the quote data from Yahoo! Finance is returned as
+            a CSV file; <tt>CSVSerializer</tt> is an implementation of the
+            <tt>org.apache.pivot.core.serialization.Serializer</tt> interface that parses a CSV
+            data stream into a sequence of name/value pairs.
+        </p>
+
+        <p>
+            By default, <tt>CSVSerializer</tt> will create an instance of
+            <tt>org.apache.pivot.collections.HashMap&lt;String, Object&gt;</tt> for each row it
+            encounters in the CSV stream. However, a caller can specify the name of a different
+            class as a constructor argument to <tt>CSVSerializer</tt>. This avoids the performance
+            penalty of traversing the data twice: once to read it from the CSV stream and again to
+            convert it to the appropriate type.
+        </p>
+
+        <p>
+            If the item class implements the <tt>org.apache.pivot.collections.Dictionary</tt>
+            interface, the parsed values are <tt>put()</tt> directly into the item instance;
+            otherwise, the item is wrapped in a <tt>org.apache.pivot.beans.BeanAdapter</tt> into
+            which the values are <tt>put()</tt> (<tt>BeanAdapter</tt> is a handy class that allows
+            a caller to treat a Java bean object as if it were a dictionary).
+        </p>
+
+        <p>
+            Stock Tracker uses the <tt>StockQuote</tt> class to represent the rows in the CSV file:
+        </p>
+
+        <pre class="brush:java">
+            
+            public class StockQuote {
+                private String symbol = null;
+                private String companyName = null;
+                private float value = 0;
+                private float openingValue = 0;
+                private float highValue = 0;
+                private float lowValue = 0;
+                private float change = 0;
+                private float volume = 0;
+
+                public String getSymbol() {
+                    return symbol;
+                }
+
+                public void setSymbol(String symbol) {
+                    this.symbol = symbol;
+                }
+
+                public String getCompanyName() {
+                    return companyName;
+                }
+
+                public void setCompanyName(String companyName) {
+                    this.companyName = companyName;
+                }
+
+                public float getValue() {
+                    return value;
+                }
+
+                public void setValue(float value) {
+                    this.value = value;
+                }
+
+                public void setValue(String value) {
+                    try {
+                        setValue(Float.parseFloat(value));
+                    } catch(NumberFormatException exception) {
+                        setValue(Float.NaN);
+                    }
+                }
+
+                public float getOpeningValue() {
+                    return openingValue;
+                }
+
+                public void setOpeningValue(float openingValue) {
+                    this.openingValue = openingValue;
+                }
+
+                public void setOpeningValue(String openingValue) {
+                    try {
+                        setOpeningValue(Float.parseFloat(openingValue));
+                    } catch(NumberFormatException exception) {
+                        setOpeningValue(Float.NaN);
+                    }
+                }
+
+                public float getHighValue() {
+                    return highValue;
+                }
+
+                public void setHighValue(float highValue) {
+                    this.highValue = highValue;
+                }
+
+                public void setHighValue(String highValue) {
+                    try {
+                        setHighValue(Float.parseFloat(highValue));
+                    } catch(NumberFormatException exception) {
+                        setHighValue(Float.NaN);
+                    }
+                }
+
+                public float getLowValue() {
+                    return lowValue;
+                }
+
+                public void setLowValue(float lowValue) {
+                    this.lowValue = lowValue;
+                }
+
+                public void setLowValue(String lowValue) {
+                    try {
+                        setLowValue(Float.parseFloat(lowValue));
+                    } catch(NumberFormatException exception) {
+                        setLowValue(Float.NaN);
+                    }
+                }
+
+                public float getChange() {
+                    return change;
+                }
+
+                public void setChange(float change) {
+                    this.change = change;
+                }
+
+                public void setChange(String change) {
+                    try {
+                        setChange(Float.parseFloat(change));
+                    } catch(NumberFormatException exception) {
+                        setChange(Float.NaN);
+                    }
+                }
+
+                public float getVolume() {
+                    return volume;
+                }
+
+                public void setVolume(float volume) {
+                    this.volume = volume;
+                }
+
+                public void setVolume(String volume) {
+                    try {
+                        setVolume(Float.parseFloat(volume));
+                    } catch(NumberFormatException exception) {
+                        setVolume(Float.NaN);
+                    }
+                }
+            }
+            
+        </pre>
+
+        <p>
+            The cell renderers assigned to the columns in the BXML file ensure that the data
+            represented by this class is formatted and presented correctly.
+        </p>
+
+        <p>
+            Finally, the query is executed:
+        </p>
+
+        <pre class="brush:java">
+            
+            getQuery.setSerializer(quoteSerializer);
+
+            getQuery.execute(new TaskAdapter&lt;Object&gt;(new TaskListener&lt;Object&gt;() {
+            ...
+            }
+            
+        </pre>
+
+        <p>
+            The argument passed to the <tt>execute()</tt> method is a <tt>TaskAdapter</tt> wrapped
+            around an anonymous inner class implementation of <tt>TaskListener&lt;Object&gt;</tt>.
+            <tt>TaskListener</tt> is an interface defined in the <tt>org.apache.pivot.util.concurrent</tt>
+            package and serves as a callback handler for asynchronous operations implemented by the
+            <tt>org.apache.pivot.util.concurrent.Task</tt> class, of which <tt>GetQuery</tt> is a subclass.
+            <tt>TaskAdapter</tt> is defined in the <tt>pivot.wtk</tt> package and ensures that the
+            callback occurs on the UI thread (otherwise, the listener is called in the context of
+            the background thread, which can produce non-deterministic results).
+        </p>
+
+        <p>
+            <tt>TaskListener</tt> defines two methods:
+        </p>
+
+        <p>
+            <tt>public void taskExecuted(Task&lt;V&gt; task);</tt><br>
+            <tt>public void executeFailed(Task&lt;V&gt; task);</tt><br>
+        </p>
+
+        <p>
+            The template parameter <tt>V</tt> is defined by the <tt>Task</tt> class and represents
+            the (optional) return value of the operation. The first method is called if the task
+            completes successfully, and the second is called if the task failed for any reason.
+        </p>
+
+        <p>
+            StockTracker's success handler is defined as follows:
+        </p>
+
+        <pre class="brush:java">
+            
+                @Override
+                public void taskExecuted(Task&lt;Object&gt; task) {
+                    if (task == getQuery) {
+                        List&lt;Object&gt; quotes = (List&lt;Object&gt;)task.getResult();
+
+                        // Preserve any existing sort and selection
+                        Sequence&lt;?&gt; selectedStocks = stocksTableView.getSelectedRows();
+
+                        List&lt;Object&gt; tableData = (List&lt;Object&gt;)stocksTableView.getTableData();
+                        Comparator&lt;Object&gt; comparator = tableData.getComparator();
+                        quotes.setComparator(comparator);
+
+                        stocksTableView.setTableData(quotes);
+
+                        if (selectedStocks.getLength() &gt; 0) {
+                            // Select current indexes of selected stocks
+                            for (int i = 0, n = selectedStocks.getLength(); i &lt; n; i++) {
+                                Object selectedStock = selectedStocks.get(i);
+
+                                int index = 0;
+                                for (Object stock : stocksTableView.getTableData()) {
+                                    String symbol = JSON.get(stock, "symbol");
+                                    String selectedSymbol = JSON.get(selectedStock, "symbol");
+
+                                    if (symbol.equals(selectedSymbol)) {
+                                        stocksTableView.addSelectedIndex(index);
+                                        break;
+                                    }
+
+                                    index++;
+                                }
+                            }
+                        } else {
+                            if (quotes.getLength() &gt; 0) {
+                                stocksTableView.setSelectedIndex(0);
+                            }
+                        }
+
+                        refreshDetail();
+
+                        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
+                            DateFormat.MEDIUM, Locale.getDefault());
+                        lastUpdateLabel.setText(dateFormat.format(new Date()));
+
+                        getQuery = null;
+                    }
+                }
+            }
+            
+        </pre>
+
+        <p>
+            If the source of the event is the currently executing task, the handler does the
+            following:
+        </p>
+
+        <ul>
+            <li>
+                <p>
+                    Caches the current sort and selection state of the quote table view
+                </p>
+            </li>
+            <li>
+                <p>
+                    Gets the result of the query and casts it to the appropriate type
+                    (<tt>List&lt;Object&gt;</tt>)
+                </p>
+            </li>
+            <li>
+                <p>
+                    Sets the list as the model data for the table view
+                </p>
+            </li>
+            <li>
+                <p>
+                    Restores any selection state (which would have been lost when the model data
+                    was reset)
+                </p>
+            </li>
+            <li>
+                <p>
+                    Updates the value of the "last updated" label to reflect the current time, in
+                    a manner appropriate for the current locale
+                </p>
+            </li>
+        </ul>
+
+        <p>
+            In the case of a failure, the handler simply logs the exception to the console:
+        </p>
+
+        <pre class="brush:java">
+            
+            @Override
+            public void executeFailed(Task&lt;Object&gt; task) {
+                if (task == getQuery) {
+                    System.err.println(task.getFault());
+                    getQuery = null;
+                }
+            }
+            
+        </pre>
+
+        <p>
+            This example demonstrates the use of <tt>GetQuery</tt> only, but Pivot also provides
+            support for HTTP POST, PUT, and DELETE operations using the <tt>PostQuery</tt>,
+            <tt>PutQuery</tt>, and <tt>DeleteQuery</tt> classes, respectively. This makes it very
+            easy to built a complete REST client using Pivot.
+        </p>
+    </div><p>Next: <a href="stock-tracker.data-binding.html">Data Binding</a></p></div></div></div><div id="footer" class="group"><div class="footerLogo">Copyright (c) 1999-2012<br>The Apache Software Foundation.</div><div class="footerLinks"><ul class="footerMenuGr"><li><strong>Demos</strong><ul><li><a href="/demos/kitchen-sink.html" target="_new">"Kitchen Sink"</a></li><li><a href="/demos/component-explorer.html" target="_new">Component Explorer</a></li><li><a href="http://cwiki.apache.org/confluence/display/PIVOT/Other+Demos" target="_new">Charting</a></li><li><a href="/demos/">More Demos</a></li></ul></li><li><strong>Documentation</strong><ul><li><a href="/getting-started.html">Getting Started</a></li><li><a href="/tutorials/">Tutorial</a></li><li><a href="/faq.html">FAQ</a></li><li><a href="/2.0.1/docs/api/">Javadoc (2.0.1)</a></li></ul></li><li><strong>Get Involved</strong><ul><li><a href="/svn.html">SVN Repositories</a></li><li><a href="/lists.html">Mailing Lists</a><
 /li><li><a href="http://issues.apache.org/jira/browse/PIVOT">Bug Database</a></li><li><a href="http://cwiki.apache.org/PIVOT/">Wiki</a></li></ul></li><li><strong>Related</strong><ul><li><a href="http://code.google.com/a/apache-extras.org/p/pivot-jfree/">JFreeChart Provider</a></li><li><a href="http://code.google.com/a/apache-extras.org/p/pivot-common/">Pivot-Common</a></li><li><a href="http://code.google.com/a/apache-extras.org/p/pivot-contrib/">Pivot-Contrib</a></li><li><a href="http://code.google.com/a/apache-extras.org/p/pivot-multilang/">Pivot-Multilang</a></li></ul></li><li><strong>About</strong><ul><li><a href="/who-we-are.html">Who We Are</a></li><li><a href="/contact.html">Contact</a></li><li><a href="http://cwiki.apache.org/confluence/display/PIVOT/News">News</a></li><li><a href="/legal.html">Legal/License</a></li></ul></li></ul></div><div class="footerLinks">
+                	Apache Pivot is a trademark of the Apache Software Foundation
+                </div></div></div></body></html>
\ No newline at end of file