<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-144505856620411498</id><updated>2024-08-30T04:14:26.696-05:00</updated><category term="notes"/><category term="HelloWorld"/><category term="Java"/><category term="Servlet"/><category term="WebDesign"/><category term="performance"/><category term="CommandFu"/><category term="Filter"/><category term="RegularExpression"/><category term="Tomcat"/><category term="Ubuntu"/><category term="algorithms"/><category term="big-oh"/><category term="data bases"/><category term="javascript"/><category term="languages"/><category term="lifecycle"/><category term="normalization"/><category term="productivity"/><category term="search"/><category term="security"/><category term="sorting"/><category term="testing"/><category term="tools"/><title type='text'>Computer Go Boom!?!</title><subtitle type='html'>A software development notebook.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-6573941940323104628</id><published>2011-06-14T14:01:00.005-05:00</published><updated>2011-06-14T15:35:48.044-05:00</updated><title type='text'>Oracle Execution Plans</title><content type='html'>&lt;h4&gt;Oracle Execution Plans&lt;/h4&gt;

&lt;p&gt;I have the privilege of working with &lt;a href=&quot;http://www.linkedin.com/in/aberdave&quot;&gt;a really great DB architect&lt;/a&gt; who taught me a superior method for viewing the detailed &lt;a href=&quot;http://en.wikipedia.org/wiki/Query_plan&quot;&gt; execution plan&lt;/a&gt; used to satisfy an Oracle query.  I&#39;m posting the details here for anyone else that needs to get such a detailed execution plan.&lt;/p&gt;

&lt;pre class=&quot;brush: sql; tab-size: 2; class-name: code&quot;&gt;
-- configure sqlplus output
set linesize 120
set pagesize 100
set serveroutput off

-- alter session to grab all stats for execution plan
alter session set statistics_level = &#39;ALL&#39;;

-- run your query of interest here
-- SELECT * FROM ???

-- revert your session
alter session set statistics_level = &#39;TYPICAL&#39;;

-- output the execution plan
select * from table (dbms_xplan.display_cursor(null, 0, &#39;ALLSTATS&#39;));
&lt;/pre&gt;

&lt;p&gt;Here&#39;s a sample of what you&#39;ll see when viewing execution plans using the strategy outline above:&lt;/p&gt;

&lt;pre class=&quot;brush: sql; tab-size: 2; class-name: code&quot;&gt;
SQL&gt; -- output the execution plan
SQL&gt; select * from table (dbms_xplan.display_cursor(null, 0, &#39;ALLSTATS&#39;));

PLAN_TABLE_OUTPUT                                                                                                       
------------------------------------------------------------------------------------------------------------------------
SQL_ID  bj0mxk7kf0dyn, child number 0                                                                                   
-------------------------------------                                                                                   
WARNING: User has no SELECT privileges on V$SQL                                                                         
                                                                                                                        
Plan hash value: 2024250754                                                                                             
                                                                                                                        
---------------------------------------------------------------------------------------------------                     
| Id  | Operation             | Name            | Starts | E-Rows | A-Rows |   A-Time   | Buffers |                     
---------------------------------------------------------------------------------------------------                     
|   1 |  NESTED LOOPS         |                 |      1 |      2 |      2 |00:00:00.01 |       6 |                     
|   2 |   INDEX FAST FULL SCAN| SYS_C0046475723 |      1 |      2 |      2 |00:00:00.01 |       4 |                     
|*  3 |   INDEX UNIQUE SCAN   | SYS_C0046475720 |      2 |      1 |      2 |00:00:00.01 |       2 |                     
---------------------------------------------------------------------------------------------------                     
                                                                                                                        
Predicate Information (identified by operation id):                                                                     
---------------------------------------------------                                                                     
                                                                                                                        
   3 - access(&quot;B&quot;.&quot;FOO_ID&quot;=&quot;F&quot;.&quot;FOO_ID&quot;)                                                                     


&lt;/pre&gt;

&lt;p&gt;There are a few things you should note in the execution plan above:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;The Operation column shows you, at a high level, what sorts of operations were used to satisfy your query.  You&#39;ll want to be on the look out for slow operations, like full table scans.&lt;/li&gt;
 &lt;li&gt;A large discrepancy between the estimated (E-Rows) and actual (A-Rows) rows can often reveal that oracle selected a poor execution plan because of stale statistics.  In such cases, you may get some relief by running the ANALYZE TABLE command to recalculate table statistics.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/6573941940323104628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2011/06/oracle-execution-plans.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/6573941940323104628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/6573941940323104628'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2011/06/oracle-execution-plans.html' title='Oracle Execution Plans'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-6587306192872782271</id><published>2011-02-04T19:57:00.012-06:00</published><updated>2012-01-31T17:08:31.787-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HelloWorld"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Hello, jQuery Form Plugin</title><content type='html'>&lt;h4&gt;Hello, jQuery Form Plugin&lt;/h4&gt;

&lt;p&gt;Lately I&#39;ve been working on a lot of ajaxy projects and have found the &lt;a href=&quot;http://jquery.malsup.com/form/&quot;&gt;jQuery Form Plugin&lt;/a&gt; to be indispensable for such work.  It&#39;s a super clean plugin for applying ajaxy behaviors to a regular ol&#39; HTML form.  To showcase the plugin here on my blog, I wrote a little &quot;Hello, World&quot; snippet that uses the plugin to pull images from &lt;a href=&quot;http://www.flickr.com/services/feeds/&quot;&gt;Flickr&#39;s image feed&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;HTML Markup&lt;/h4&gt;

&lt;p&gt;First, let&#39;s get our markup on.  We&#39;ll build a vanilla HTML form that asks the user for a tag to be searched on &lt;a href=&quot;http://www.flickr.com/&quot;&gt;Flickr&lt;/a&gt;.  After the form, we&#39;ll also declare an empty &amp;lt;div&amp;gt; that will eventually be updated with the results of our Flickr tag search.&lt;/p&gt;

&lt;pre class=&quot;brush: html; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;form id=&amp;quot;flickrSearchForm&amp;quot; method=&amp;quot;get&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;
    &amp;lt;label for=&amp;quot;tags&amp;quot;&amp;gt;Photos tagged with &amp;lt;/label&amp;gt;
    &amp;lt;input id=&amp;quot;tags&amp;quot; name=&amp;quot;tags&amp;quot; placeholder=&amp;quot;any Flickr tag&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Find&amp;quot; /&amp;gt;
&amp;lt;/form&amp;gt;

&amp;lt;div id=&amp;quot;flickrSearchResults&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;jQuery Dependencies&lt;/h4&gt;

&lt;p&gt;Next we need to include jQuery and the &lt;a href=&quot;http://jquery.malsup.com/form/&quot;&gt;jQuery Form Plugin&lt;/a&gt;.  The base jQuery library is available via Google&#39;s CDN.  The form plugin is hosted on github.&lt;/p&gt;

&lt;pre class=&quot;brush: html; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; 
 src=&amp;quot;https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; 
 src=&amp;quot;http://malsup.github.com/jquery.form.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;Unobtrusive Goodness&lt;/h4&gt;

&lt;p&gt;Now we can finally get down to the business of unobtrusively wiring some ajax operations into the otherwise unremarkable HTML form.&lt;/p&gt;

&lt;pre class=&quot;brush: javascript; tab-size: 2; class-name: code&quot;&gt;
// apply form plugin
jQuery(&#39;#flickrSearchForm&#39;).ajaxForm({
 url: &#39;http://api.flickr.com/services/feeds/photos_public.gne&#39;,
 data: { 
  tagmode: &#39;any&#39;, 
  format: &#39;json&#39;, 
  jsoncallback: &#39;displayFlickrSearchResults&#39;
 },
 type: &#39;get&#39;,
 dataType: &#39;script&#39;,
 beforeSubmit: function(formDataArray, form, options) { 
  disableSubmitAndClearPreviousResults(); 
 }
});
&lt;/pre&gt;

&lt;p&gt;How easy was that?  With just a few lines of code we decorated the form to fire off an ajax request to Flickr when the user presses the submit button.  The form plugin took care of a lot of little details like ...&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;providing a pre-submit hook for clearing out previous search results&lt;/li&gt;
 &lt;li&gt;serializing the form&#39;s inputs into the ajax request&#39;s query string&lt;/li&gt;
 &lt;li&gt;appending some constant data values to the ajax request&#39;s query string&lt;/li&gt;
 &lt;li&gt;automatically invoking the result of the &lt;a href=&quot;http://remysharp.com/2007/10/08/what-is-jsonp/&quot;&gt;JSONP&lt;/a&gt; response as a JavaScript function&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;End Result&lt;/h4&gt;

&lt;p&gt;Here&#39;s the end result once the code snippets above are put together.&lt;/p&gt;

&lt;form id=&quot;flickrSearchForm&quot; method=&quot;get&quot; action=&quot;&quot;&gt;
    &lt;label for=&quot;tags&quot;&gt;Photos tagged with &lt;/label&gt;
    &lt;input id=&quot;tags&quot; name=&quot;tags&quot; placeholder=&quot;any Flickr tag&quot; /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;Find&quot; /&gt;
&lt;/form&gt;
&lt;br/&gt;
&lt;div id=&quot;flickrSearchResults&quot;&gt;&lt;/div&gt;

&lt;style type=&quot;text/css&quot;&gt;
 #flickrSearchResults img {
  margin: 1em;
  border: none;
 }
&lt;/style&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://malsup.github.com/jquery.form.js&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
 
 // wait for DOM to be ready
 jQuery(function() { 

  // apply form plugin to form
  jQuery(&#39;#flickrSearchForm&#39;).ajaxForm({
   url: &#39;http://api.flickr.com/services/feeds/photos_public.gne&#39;,
   data: { tagmode: &#39;any&#39;, format: &#39;json&#39;, jsoncallback: &#39;displayFlickrSearchResults&#39; },
   type: &#39;get&#39;,
   dataType: &#39;script&#39;,
   beforeSubmit: function(formDataArray, form, options) { disableSubmitAndClearPreviousResults(); }
  });

 });

 // a little helper function
 disableSubmitAndClearPreviousResults = function() {
  // disable submit button
  jQuery(&#39;input[type=submit]&#39;).attr(&#39;disabled&#39;, &#39;disabled&#39;);

  // clear and hide results div
  jQuery(&#39;#flickrSearchResults&#39;).html(&#39;&#39;).hide();
 };

 // another little helper function
 displayFlickrSearchResults = function(response) {
  // construct HTML results string
  var htmlFlickrResults = &#39;&lt;h3&gt;&#39; + response.title + &#39;&lt;/h3&gt;&#39;;

  var flickrResultItems = response.items;
  for (var i = 0; i &lt; flickrResultItems.length; i++) {
   var flickrResultItem = flickrResultItems[i];
   htmlFlickrResults += &#39;&lt;a target=&quot;_blank&quot; href=&quot;&#39; + (flickrResultItem.link) + &#39;&quot;&gt;&#39;;
   htmlFlickrResults += &#39;&lt;img class=&quot;flickrResult&quot; src=&quot;&#39; + (flickrResultItem.media.m) + &#39;&quot; title=&quot;&#39; + (flickrResultItem.title) + &#39;&quot;&gt;&lt;/img&gt;&#39;;
  }

  // insert results to DOM and reveal
  jQuery(&#39;#flickrSearchResults&#39;).html(htmlFlickrResults).slideDown(&#39;slow&#39;, function() { 

   // re-enable submit button now that search results have been revealed
   jQuery(&#39;input[type=submit]&#39;).removeAttr(&#39;disabled&#39;); 

  });
 };

&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/6587306192872782271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2011/02/hello-jquery-form-plugin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/6587306192872782271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/6587306192872782271'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2011/02/hello-jquery-form-plugin.html' title='Hello, jQuery Form Plugin'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-5469514527498364532</id><published>2011-01-17T16:10:00.010-06:00</published><updated>2011-01-24T21:06:49.656-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CommandFu"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><category scheme="http://www.blogger.com/atom/ns#" term="WebDesign"/><title type='text'>What Have You Done for Me, Latency?</title><content type='html'>&lt;p&gt;When developing web applications, it&#39;s not uncommon to develop and deploy the application on different network topoligies.  During development, for example, you might be running a database server, web server and web browser all on localhost.  Your application is running well and the performance is snappy.  But user experience starts to lag when the application is deployed to production where web server and database reside on different boxes.  What&#39;s to blame?  &lt;a href=&quot;http://rescomp.stanford.edu/~cheshire/rants/Latency.html&quot;&gt;Latency&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But fear not, intrepid programmer!  Here&#39;s a simple command line hack that you can use to make network performance on localhost more closely resemble WAN or LAN performance.&lt;/p&gt;

&lt;pre class=&quot;brush: bash; tab-size: 2; class-name: code&quot;&gt;#!/bin/bash

# This script adds a tc rule to the loopback device to 
# help developers approximate WAN performance on their 
# loopback device.

# add a delay rule to the loopback device
sudo tc qdisc replace dev lo root handle 1:0 netem delay 10msec 5msec 10%

# list current state of the loopback device
echo &#39;Loopback device is now configured to simulate a high latency network route.&#39;
echo &#39;&#39;
echo &quot;Current dev lo rules ... `tc qdisc show dev lo`&quot;
echo &#39;&#39;
echo &#39;&#39;

# demonstrate delay by pinging localhost
ping -c 3 localhost
&lt;/pre&gt;

&lt;p&gt;I run the above commands on login so that overly chatty code doesn&#39;t sneak past.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/5469514527498364532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2011/01/what-have-you-done-for-me-latency.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/5469514527498364532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/5469514527498364532'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2011/01/what-have-you-done-for-me-latency.html' title='What Have You Done for Me, Latency?'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-8002532435355180385</id><published>2011-01-09T23:31:00.024-06:00</published><updated>2011-01-16T22:37:32.525-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HelloWorld"/><category scheme="http://www.blogger.com/atom/ns#" term="WebDesign"/><title type='text'>Hello, CSS3</title><content type='html'>&lt;h4&gt;Hello, CSS3&lt;/h4&gt;

&lt;p&gt;This week I&#39;m all about embracing new-ish web standards.  In a prior post, I marked up an &lt;a href=&quot;./hello-html5.html&quot;&gt;HTML5 &quot;Hello, World!&quot;&lt;/a&gt; document using new semantic tags.  Today I&#39;m going to apply some CSS2 and CSS3 styles to that document to demonstrate the &lt;a href=&quot;http://www.css3.info/preview/&quot;&gt;awesome new design features that are available in CSS3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, let&#39;s start by checking out how the HTML5 &quot;Hello, World!&quot; document renders without any styling applied:&lt;/p&gt;

&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9K6rjsZhZuq-cmeVwRS4gY8NcA72bK0LV8Ct3VPQ5dSmaddF0uP3nGDe2itepPfCFwIw8Zyu1Q_X_an98COaS_Swcr4U4_eDkdcAUap3UbgzpVAqeK4mxArkD8xzyJPAI-sV4gNmQVn8/s1600/1.png&quot;&gt;&lt;img style=&quot;cursor:pointer; cursor:hand;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9K6rjsZhZuq-cmeVwRS4gY8NcA72bK0LV8Ct3VPQ5dSmaddF0uP3nGDe2itepPfCFwIw8Zyu1Q_X_an98COaS_Swcr4U4_eDkdcAUap3UbgzpVAqeK4mxArkD8xzyJPAI-sV4gNmQVn8/s400/1.png&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5562837369814673474&quot; /&gt;&lt;/a&gt;

&lt;p&gt;No surprises in the screenshot above.  The document gets rendered with just a bit of formatting for headers, lists &amp; links.  Let&#39;s add some CSS2 styles to spruce things up a bit.&lt;/p&gt;

&lt;pre class=&quot;brush: css; tab-size: 2; class-name: code&quot;&gt;article,aside,figure,footer,header,hgroup,nav,section {
 /* setup for browsers that don&#39;t yet recognize HTML5 
    block elements */
 display:block
}
p {
 /* add a bit of margin above and 
    below all paragraphs */
 margin: 0.5em 0em;
}
html {
 /* stretch body to fill extra browser height */
 height: 98%;
 /* define color for dead space on 
    left and right of page body */
 background-color: #D0D3A6;
}
body {
 /* stretch body to fill extra browser height */
 min-height: 98%;
 /* define content width */
 width:46em;
 /* center content in the browser window */
 margin: 0 auto;
 /* background color for body content */
 background-color: #FFFFFF;
 /* and a wee bit of padding for all 
    top-level elements in the body */
 padding: 0.5em 1.5em;
}
body &amp;gt; header {
 /* keep the header from being crowded */
 margin-bottom: 0.25em;
}
body &amp;gt; header &amp;gt; hgroup { 
 /* style the page&#39;s header */
 padding: 0.25em;
 margin-bottom: 0.5em;
 background-color: #BC9C73;
 text-align: center;
}
body &amp;gt; header &amp;gt; nav { 
 /* style the page&#39;s navigation content */
 background-color: #486997;
 /* define bottom border to force render of 
   child ul&#39;s bottom margin */
 border-bottom: 0.1em solid #486997;
}
body &amp;gt; header &amp;gt; nav a {
 /* style the page&#39;s navigation content */
 color: #FFFFFF;
 text-decoration: none;
}
body &amp;gt; header &amp;gt; nav ul { 
 /* style the page&#39;s navigation content */
 background-color: #688AB6;
 margin: 0em 0em 0.3em 0em;
 padding: 1em 0.75em 0em 0.75em;
}
body &amp;gt; header &amp;gt; nav ul li {
 /* style the page&#39;s navigation content */
 background-color: #486997;
 padding: 0.3em 1em;
 margin: 0em 0.15em;
 display: inline;
}
body &amp;gt; footer {
 /* render the footer in the center, below 
    all other content */
 text-align: center;
 clear: both;
}
h1 {
 text-transform: capitalize;
}
h1,h2 {
 font-size:medium;
 margin: 0.5em 0em 0.25em 0em;
}
div#main {
 /* float main content to the left */
 float: left;
 width: 74%;
}
div#sidebar {
 /* float sidebar content to the right */
 float: right;
 width: 24%;
}

body aside,
body section {
 /* keep content containers from feeling crowded */
 padding: 0.25em;
 margin: 0.25em 0em;
}&lt;/pre&gt;

&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9CSCy7nr2_DQz-Cgxa7CXtTaKgB5ypCk-vMI7kiUiyZ8PIbM4CsSmYFRvAL8BsFFqOEwipyv2MaaM0NfW4Em3C9oKhuPJ4FAJ1FNKFwAYXxNdZB-Mug2eu-cAY0hWk-fdZ2GwAIjjncI/s1600/2.png&quot;&gt;&lt;img style=&quot;cursor:pointer; cursor:hand;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9CSCy7nr2_DQz-Cgxa7CXtTaKgB5ypCk-vMI7kiUiyZ8PIbM4CsSmYFRvAL8BsFFqOEwipyv2MaaM0NfW4Em3C9oKhuPJ4FAJ1FNKFwAYXxNdZB-Mug2eu-cAY0hWk-fdZ2GwAIjjncI/s400/2.png&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5562846356242269346&quot; /&gt;&lt;/a&gt;

&lt;p&gt;Well, that&#39;s certainly an improvement.  But we can do even better by progressively enhancing the page with some additional CSS3 rules.  Let&#39;s give the page some depth and texture.&lt;/p&gt;

&lt;pre class=&quot;brush: css; tab-size: 2; class-name: code&quot;&gt;/*  many of these rules generated with 
    the awesome http://css3generator.com/ or
    http://www.colorzilla.com/gradient-editor/ tools */

body { 
 /* round the corners of the body element&#39;s border */
 -moz-border-radius: 4px;
 border-radius: 4px; 
 
 /* apply inset box shadow to body element to 
    create the illusion of depth */
 -webkit-box-shadow: inset 2px 0px 25px #333333;
 -moz-box-shadow: inset 2px 0px 25px #333333;
 box-shadow: inset 2px 0px 25px #333333; 
}

h1, h2 {
 /* apply drop shadow to header text */
 text-shadow: 1px 1px 2px #333333;
 filter: dropshadow(color=#333333, offx=1, offy=1); 
}

body &amp;gt; header * { 
 /* by default, round the border corners of 
    all elements in the header */
 -moz-border-radius: 4px;
 border-radius: 4px; 
}

body &amp;gt; header &amp;gt; hgroup,
body &amp;gt; header &amp;gt; nav { 
 /* apply box shadows to top-level header containers 
    to create the illusion of depth */
 -webkit-box-shadow: 2px 4px 6px #333333;
 -moz-box-shadow: 2px 4px 6px #333333;
 box-shadow: 2px 4px 6px #333333; 
}

body &amp;gt; header &amp;gt; hgroup { 
 /* add a subtle gradient to header&#39;s background */
 background: -moz-linear-gradient(top, #BC9C73 0%, #D3BFA5 100%); /* firefox */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#BC9C73), color-stop(100%,#D3BFA5)); /* webkit */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=&#39;#BC9C73&#39;, endColorstr=&#39;#D3BFA5&#39;,GradientType=0 ); /* ie */
}

body &amp;gt; header &amp;gt; nav ul {
 /* &amp;quot;square&amp;quot; the dividing line between navigation 
    tabs and their background */
 -moz-border-radius-bottomright: 0px;
 -moz-border-radius-bottomleft: 0px;
 border-bottom-right-radius: 0px;
 border-bottom-left-radius: 0px; 
}

body &amp;gt; header &amp;gt; nav ul li {
 /* round the top corners of the navigation links */
 -moz-border-radius-topleft: 10px;
 -moz-border-radius-topright: 10px;
 -moz-border-radius-bottomright: 0px;
 -moz-border-radius-bottomleft: 0px;
 border-top-left-radius: 10px;
 border-top-right-radius: 10px;
 border-bottom-right-radius: 0px;
 border-bottom-left-radius: 0px; 

 /* add a gradient to the background of our 
    navigation links */
 background: -moz-linear-gradient(top, #c3d9ff 0%, #486997 37%, #486997 100%); /* firefox */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c3d9ff), color-stop(37%,#486997), color-stop(100%,#486997)); /* webkit */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=&#39;#c3d9ff&#39;, endColorstr=&#39;#486997&#39;,GradientType=0 ); /* ie */
 
 /* apply a more drop shadow to navigation link text */
 text-shadow: 1px 2px 8px #ffffff;
 filter: dropshadow(color=#ffffff, offx=1, offy=2); 
}

body section,
body aside {
 /* round the corners of top-level semantic elements */
 -moz-border-radius: 4px;
 border-radius: 4px; 

 /* apply a gradient background &amp;quot;smear&amp;quot; 
    to top-level semantic elements */
 background: #FFFFFF; /* use white background if gradient not available*/
 background: -moz-linear-gradient(top, #D3BFA5 0%, #FFFFFF 33%); /* firefox */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#D3BFA5), color-stop(33%,#FFFFFF)); /* webkit */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=&#39;#D3BFA5&#39;, endColorstr=&#39;#FFFFFF&#39;,GradientType=0 ); /* ie */
}&lt;/pre&gt;

&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdTc8XFSpqh77u-TD6yq5IShlYZuHqkozWhfLbsgF5gAkudeCM6rFbsoCnZH6mImcU_hippxQzbt1x18StmcZ3jFe0VAgaKR6btkJ55xqcH03YBa3h1f3gL06UQs_LY6NbkFfD-JoNg1U/s1600/3.png&quot;&gt;&lt;img style=&quot;cursor:pointer; cursor:hand;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdTc8XFSpqh77u-TD6yq5IShlYZuHqkozWhfLbsgF5gAkudeCM6rFbsoCnZH6mImcU_hippxQzbt1x18StmcZ3jFe0VAgaKR6btkJ55xqcH03YBa3h1f3gL06UQs_LY6NbkFfD-JoNg1U/s400/3.png&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5562850040985588994&quot; /&gt;&lt;/a&gt;

&lt;p&gt;Many of the CSS3 rules used above were generated with the awesome &lt;a href=&quot;http://css3generator.com/&quot;&gt;CSS3 Generator&lt;/a&gt; and &lt;a href=&quot;http://www.colorzilla.com/gradient-editor/&quot;&gt;ColorZilla Gradient Generator&lt;/a&gt; tools.  I highly recommend checking them out!&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/8002532435355180385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2011/01/hello-css3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/8002532435355180385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/8002532435355180385'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2011/01/hello-css3.html' title='Hello, CSS3'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9K6rjsZhZuq-cmeVwRS4gY8NcA72bK0LV8Ct3VPQ5dSmaddF0uP3nGDe2itepPfCFwIw8Zyu1Q_X_an98COaS_Swcr4U4_eDkdcAUap3UbgzpVAqeK4mxArkD8xzyJPAI-sV4gNmQVn8/s72-c/1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-2176586389346405408</id><published>2011-01-09T23:30:00.011-06:00</published><updated>2011-01-16T22:42:43.840-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HelloWorld"/><category scheme="http://www.blogger.com/atom/ns#" term="WebDesign"/><title type='text'>Hello, HTML5</title><content type='html'>&lt;h4&gt;Hello, HTML5&lt;/h4&gt;

&lt;p&gt;This week I&#39;ve been skimming Mark Pilgrim&#39;s &lt;a href=&quot;http://www.amazon.com/HTML5-Up-Running-Mark-Pilgrim/dp/0596806027&quot;&gt;&lt;i&gt;HTML5: Up and Running&lt;/i&gt;&lt;/a&gt; book with a keen interest in the &lt;a href=&quot;http://dev.w3.org/html5/html4-differences/#new-elements&quot;&gt;new semantic elements&lt;/a&gt; that are being formalized as part of the HTML 5 spec.  There are some great new semantic elements being proposed to replace pervasive, unformalized web developer memes like ...&lt;/p&gt;

&lt;pre class=&quot;brush: html; tab-size: 2; class-name: code&quot;&gt;
 &amp;lt;!-- This is _so_ 2008. --&amp;gt;
 &amp;lt;div id=&quot;header&quot;&amp;gt;
  &amp;lt;ul id=&quot;navigation&quot;&amp;gt;&amp;lt;/ul&amp;gt;
 &amp;lt;/div&amp;gt;
 &amp;lt;div id=&quot;content&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div id=&quot;main&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div id=&quot;sidebar&quot;&amp;gt;&amp;lt;/div&amp;gt;
 &amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Notice in the above markup that the semantic info about each &amp;lt;div&amp;gt;&#39;s purpose is captured in its id attribute.  This is totally valid markup and will produce a well organized document, but it does have some serious drawbacks.  While such a id-as-semantic-messenger anti-pattern is easily understood by a human web developer, it&#39;s not easily parsed by machines.&lt;/p&gt;

&lt;p&gt;So why, you may ask, should we care whether machines can understand the semantics of our web pages?  Aren&#39;t web pages designed to be read and understood by humans?  No.  Not, all humans &lt;u&gt;read&lt;/u&gt; web pages.  People with visual impairments have the web read to them by &lt;a href=&quot;http://en.wikipedia.org/wiki/Screen_reader&quot;&gt;screen readers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Screen readers aren&#39;t that great.  Yet.  For example, whereas a human can easily and reliably find the main navigation content of a web page, screen readers don&#39;t yet support jumping straight to a page&#39;s main navigation content.  Consider the myriad HTML4 variations that a screen reader would have to handle in order to support a jump-straight-to-navigation feature:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&amp;lt;ul id=&quot;navigation&quot;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/li&gt;
 &lt;li&gt;&amp;lt;ul id=&quot;nav&quot;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/li&gt;
 &lt;li&gt;&amp;lt;div id=&quot;navigation&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/li&gt;
 &lt;li&gt;&amp;lt;ul id=&quot;navigacion&quot;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/li&gt;
 &lt;li&gt;&amp;lt;ul id=&quot;menu_bar&quot;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/li&gt;
 &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTML5 to the rescue!  Writing screen readers that can find the &lt;a href=&quot;http://www.w3.org/TR/html5/sections.html#the-nav-element&quot;&gt;&amp;lt;nav&amp;gt;&lt;/a&gt; element in a HTML5 document will be much easier than coding to handle the tag soup detailed above.  And &amp;lt;nav&amp;gt; is not the only new semantic element that will make it easier to write better screen readers.  HTML5 also defines &lt;a href=&quot;http://www.w3.org/TR/html5/sections.html#the-header-element&quot;&gt;&amp;lt;header&amp;gt;&lt;/a&gt;, &lt;a href=&quot;http://www.w3.org/TR/html5/sections.html#the-footer-element&quot;&gt;&amp;lt;footer&amp;gt;&lt;/a&gt;, &lt;a href=&quot;http://www.w3.org/TR/html5/sections.html#the-section-element&quot;&gt;&amp;lt;section&amp;gt;&lt;/a&gt; and &lt;a href=&quot;http://www.w3.org/TR/html5/sections.html#the-aside-element&quot;&gt;&amp;lt;aside&amp;gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That&#39;s great news.  As a &lt;a href=&quot;http://twingate2010.blogspot.com/2011/01/and-were-back-ten-things-that-have.html&quot;&gt;father of a visually impaired child&lt;/a&gt;, I&#39;m hoping that future screen reader software can provide my daughter with web interactions that are as rich as those that I enjoy.  With that vision of the future in mind, I&#39;m embracing HTML5 and have authored a quick &quot;Hello, World!&quot; example of HTML5 semantic elements in action.&lt;/p&gt;

&lt;pre class=&quot;brush: html; tab-size: 2; class-name: code&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;

&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
  &amp;lt;title&amp;gt;Hello, HTML5 Semantic Elements!&amp;lt;/title&amp;gt;
  &amp;lt;!--[if lt IE 9]&amp;gt;
    &amp;lt;script 
      src=&amp;quot;http://html5shiv.googlecode.com/svn/trunk/html5.js&amp;quot;&amp;gt;
    &amp;lt;/script&amp;gt;
  &amp;lt;![endif]--&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;

  &amp;lt;header&amp;gt;
    &amp;lt;hgroup&amp;gt;
      &amp;lt;h1&amp;gt;Lorem ipsum ...&amp;lt;/h1&amp;gt;
      &amp;lt;h2&amp;gt;dolor sit amet, consectetur adipiscing.&amp;lt;/h2&amp;gt;
    &amp;lt;/hgroup&amp;gt;
    &amp;lt;nav&amp;gt;
      &amp;lt;ul&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;a&amp;gt;Donec hendrerit&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;a&amp;gt;Pellentesque eget turpis&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;a&amp;gt;Quisque facilisis porttitor&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/nav&amp;gt;
  &amp;lt;/header&amp;gt;

  &amp;lt;div id=&amp;quot;main&amp;quot;&amp;gt;

    &amp;lt;section&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;h2&amp;gt;Morbi a posuere magna&amp;lt;/h2&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;p&amp;gt;Etiam feugiat pellentesque dapibus...&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;Phasellus ullamcorper condimentum urna...&amp;lt;/p&amp;gt;
    &amp;lt;/section&amp;gt;

    &amp;lt;section&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;h2&amp;gt;Donec posuere lobortis ipsum&amp;lt;/h2&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;p&amp;gt;Cras tellus odio, facilisis nec porttitor...&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;Donec blandit suscipit urna ac luctus...&amp;lt;/p&amp;gt;
    &amp;lt;/section&amp;gt;

  &amp;lt;/div&amp;gt;

  &amp;lt;div id=&amp;quot;sidebar&amp;quot;&amp;gt;

    &amp;lt;aside&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;h2&amp;gt;Ut tincidunt tincidunt&amp;lt;/h2&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;p&amp;gt;Suspendisse varius, lacus a egestas...&amp;lt;/p&amp;gt;
    &amp;lt;/aside&amp;gt;

    &amp;lt;aside&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;h2&amp;gt;Praesent massa sapien&amp;lt;/h2&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;p&amp;gt;Phasellus porttitor auctor sapien at...&amp;lt;/p&amp;gt;
    &amp;lt;/aside&amp;gt;

  &amp;lt;/div&amp;gt;

  &amp;lt;footer&amp;gt;
    &amp;lt;p&amp;gt;&amp;amp;copy; 2010 Dave Wingate&amp;lt;/p&amp;gt;
  &amp;lt;/footer&amp;gt;  

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/2176586389346405408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2011/01/hello-html5.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/2176586389346405408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/2176586389346405408'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2011/01/hello-html5.html' title='Hello, HTML5'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-4380015253899656240</id><published>2010-11-28T15:23:00.023-06:00</published><updated>2011-01-16T22:57:46.001-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="languages"/><category scheme="http://www.blogger.com/atom/ns#" term="notes"/><title type='text'>Course Notes -- Design of Programming Languages (CS5318)</title><content type='html'>&lt;p&gt;This week I&#39;m revisiting some old course notes that I originally published on &lt;a href=&quot;http://www.big-oh.net&quot;&gt;www.big-oh.net&lt;/a&gt;.  I&#39;m moving away from self-hosting content on that domain, migrating blog-style content into the cloud ... &lt;a href=&quot;http://computergoboom.blogspot.com/&quot;&gt;Blogger&lt;/a&gt; in this case.&lt;/p&gt;

&lt;p&gt;Following are notes that I used to study for the &lt;a href=&quot;http://www.cs.txstate.edu/courses/courseinfo.php?course_id=CS%205318&quot;&gt;Design of Programming Languages&lt;/a&gt; section of the &lt;a href=&quot;http://www.cs.txstate.edu/graduate_program/comps/&quot;&gt;Texas State University Computer Science graduate comprehensive examination&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;h4&gt;Language Design Criteria&lt;/h4&gt;

&lt;p&gt;The sub-headings below catalog some of the most important language design criteria.&lt;/p&gt;

&lt;h5&gt;Efficiency&lt;/h5&gt;

&lt;p&gt;The efficiency of a programming language relates to the speed/cost of performing basic activities of a language&#39;s lifecycle.  Many facets of a programming language can be evaluated with respect to efficiency.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Efficiency of Execution - Influenced by language features like recursion and dynamic memory allocation.&lt;/li&gt;
 &lt;li&gt;Efficiency in Translation - How many passes does the compiler need?&lt;/li&gt;
 &lt;li&gt;Efficiency in Implementation - Influenced by the number of features provided and by level of orthogonality.&lt;/li&gt;
 &lt;li&gt;Efficiency in Programming - Time to train programmers and time to solve problems in the language.&lt;/li&gt;
 &lt;li&gt;Efficiency in Maintenance - Largely determined by readability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Regularity&lt;/h5&gt;

&lt;p&gt;The regularity of a language relates to the interaction of its features.  A language&#39;s regularity can be further decomposed into the following characteristics.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Generality - A language is general if there are no special cases in the availability or use of the language&#39;s operators.  An example of failed generality in the C language is that individual items can be compared with the &quot;==&quot; operator, but entire structs cannot be compared using that operator.&lt;/li&gt;
 &lt;li&gt;Orthogonality - The constructs of a language are orthogonal if they do not behave differently in different contexts and can be easily combined in all meaningful ways.  An example of failed orthogonality in the C language is that local variables can only be defined at the beginning of the block.&lt;/li&gt;
 &lt;li&gt;Uniformity - In a uniform language, things that are similar should look similar and things that are different should look different.  An example of failed uniformity in the C language is that the difference between &quot;=&quot; and &quot;==&quot; is confusing.&lt;/li&gt;
&lt;/ul&gt;
 
&lt;h5&gt;Simplicity&lt;/h5&gt;

&lt;p&gt;Simple languages have the following properties.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Simple languages have fewer features, which makes them easier to implement.&lt;/li&gt;
 &lt;li&gt;Simple languages may have increased implementation efficiency, but decreased programming efficiency and decreased expressiveness.&lt;/li&gt;
&lt;/ul&gt;
    
&lt;h4&gt;Abstraction&lt;/h4&gt;

&lt;p&gt;Abstractions hide unnecessary details, those that are only relevant to the internal implementation.  For example, the String data type is an abstraction in that it hides the implementation details of storing and manipulating character data.  Another example abstraction is that the &quot;if&quot; statement is an abstraction in that it eliminates the need to consider logic-based jump commands.&lt;/p&gt;

&lt;p&gt;The table below describes a taxonomy of abstraction levels in programming languages.&lt;/p&gt;

&lt;table border=&quot;2&quot;&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Abstraction Level&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Data&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Control&lt;/b&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Basic&lt;/td&gt;
  &lt;td&gt;Variables as abstractions for memory locations.&lt;/td&gt;
  &lt;td&gt;Variable assignment and jump statements.&lt;/td&gt;

 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Structured&lt;/td&gt;
  &lt;td&gt;Arrays, records, structs, classes, lists, etc.&lt;/td&gt;
  &lt;td&gt;Guarded commands.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Unit&lt;/td&gt;
  &lt;td colspan=&quot;2&quot;&gt;Packages, components, libraries, etc.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Parallel&lt;/td&gt;
  &lt;td colspan=&quot;2&quot;&gt;Threads, processes, tasks, etc.&lt;/td&gt;
 &lt;/tr&gt;
&lt;/table&gt;

&lt;br/&gt;

&lt;h4&gt;Computational Paradigms&lt;/h4&gt;

&lt;p&gt;A single programming language may support one or more computational paradigms.  The sub-headings below details some of the computational paradigms covered by the comprehensive exam.&lt;/p&gt;
    
 
&lt;h5&gt;Imperative&lt;/h5&gt;

&lt;p&gt;The imperative computational paradigm is closely tied to the structure of the von Neumann computer model.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;A.k.a. procedural.&lt;/li&gt;
 &lt;li&gt;Examples include Fortran, C, Pascal and Algol&lt;/li&gt;
 &lt;li&gt;Characterized by sequenced instruction execution, loops, and variables that represent memory locations.&lt;/li&gt;
&lt;/ul&gt;
 
&lt;h5&gt;Functional&lt;/h5&gt;

&lt;p&gt;The functional computational paradigm structures programs in a manner that mirrors the structure of lambda-calculus.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;A.k.a. applicative.&lt;/li&gt;
 &lt;li&gt;Examples include Lisp, Miranda and Scheme.&lt;/li&gt;
 &lt;li&gt;Reasoning about this type of programs is easier because it is based on recursive function theory.&lt;/li&gt;
 &lt;li&gt;Characterized by (recursive) function calls as the basis for program control.  Instead of having variables that represent memory locations, this paradigm has function parameters that accept input values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Logic&lt;/h5&gt;

&lt;p&gt;The logical computational paradigm is a higher-level paradigm that abstracts away the need to describe &quot;what to do,&quot; requiring that the programmer describe only &quot;what s/he wants.&quot;&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;A.k.a. declarative.&lt;/li&gt;
 &lt;li&gt;Examples include Prolog and SQL.&lt;/li&gt;
 &lt;li&gt;Characterized by variables that represent partial computations, which are inputs to Horn clause resolution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Programming Language Levels&lt;/h4&gt;

&lt;p&gt;When writing a program in any language, errors can arise at many different levels:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  Lexical - identifiers, operators, separators, comments&lt;br/&gt;
  &lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;// not a valid operator or identifier
int x#1 = 2;&lt;/pre&gt;
 &lt;/li&gt;
 &lt;li&gt;
  Context-Free Syntax - dictates the form of statements, functions, modules, etc.&lt;br/&gt;
  &lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;// missing parentheses violates 
// if statement syntax
if x == y { a=b; }&lt;/pre&gt;
 &lt;/li&gt;
 &lt;li&gt;
  Context-Sensitive Syntax - type checking, forward references, variable declaration, etc.&lt;br/&gt;
  &lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;// duplicate variable declaration
double a;
...
int a; 
  &lt;/pre&gt;
 &lt;/li&gt;
 &lt;li&gt;
  Dynamic Semantics - divide by zero, use of un-initialized variable, etc.&lt;br/&gt;
  &lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;double a = 0;
double b = 12 / a;
  &lt;/pre&gt;
 &lt;/li&gt; 
&lt;/ul&gt;

&lt;h4&gt;Grammars&lt;/h4&gt;

&lt;h5&gt;Definition&lt;a name=&quot;Definition&quot;&gt;&lt;/a&gt;&lt;/h5&gt;

&lt;p&gt;A grammar is defined by:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;A finite set of non-terminal symbols.&lt;/li&gt;
    &lt;li&gt;A finite set of terminal symbols.&lt;/li&gt;
    &lt;li&gt;A single start symbol.&lt;/li&gt;
    &lt;li&gt;A finite set of production rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Context-Free Grammars&lt;/h5&gt;

&lt;p&gt;A Context-free grammar consists of a series of grammar rules that observe the form:&lt;/p&gt;

&lt;pre class=&quot;brush: text; tab-size: 2; class-name: code&quot;&gt;Non-terminal -&amp;gt; {terminals and non-terminals}&lt;/pre&gt;

&lt;p&gt;This type of grammar is context-free because each left-hand-side non-terminal can always be replaced by any right-hand-side choice, no matter where the non-terminal might appear.&lt;/p&gt;

&lt;p&gt;Additionally, a context-free grammar also has a distinguished non-terminal called a start symbol.  The language for the grammar is the set of all strings of terminals that can be derived from the start symbol.&lt;/p&gt;

&lt;p&gt;By defining a programming language using a context-free grammar, the grammar also implicitly defines the steps that a parser must take to construct a parse tree for a string.&lt;/p&gt;  
    
&lt;h5&gt;Attribute Grammars&lt;/h5&gt;

&lt;p&gt;Attribute grammars are an extension of context-free grammars.  Because context-free grammars describe only the lexical and syntax levels of a language, they are unable to describe many features of modern programming languages.  For example, context-free grammars are unable to enforce type checking.  Attribute grammars provide the ability to enforce static semantic rules, like type checking.&lt;/p&gt;

&lt;p&gt;An attribute grammar has these properties:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Each grammar symbol has a set of (inherited or synthesized) attributes.&lt;/li&gt;
 &lt;li&gt;Each grammar rule has a set of (semantic of predicate) functions, which are defined over the attributes of the symbols in the rule.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/4380015253899656240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-design-of-programming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/4380015253899656240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/4380015253899656240'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-design-of-programming.html' title='Course Notes -- Design of Programming Languages (CS5318)'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-8336796896616892857</id><published>2010-11-28T15:22:00.021-06:00</published><updated>2011-01-16T22:56:35.743-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="algorithms"/><category scheme="http://www.blogger.com/atom/ns#" term="big-oh"/><category scheme="http://www.blogger.com/atom/ns#" term="notes"/><category scheme="http://www.blogger.com/atom/ns#" term="sorting"/><title type='text'>Course Notes -- Algorithm Design and Analysis (CS5329)</title><content type='html'>&lt;p&gt;This week I&#39;m revisiting some old course notes that I originally published on &lt;a href=&quot;http://www.big-oh.net&quot;&gt;www.big-oh.net&lt;/a&gt;.  I&#39;m moving away from self-hosting content on that domain, migrating blog-style content into the cloud ... &lt;a href=&quot;http://computergoboom.blogspot.com/&quot;&gt;Blogger&lt;/a&gt; in this case.&lt;/p&gt;

&lt;p&gt;Following are notes that I used to study for the &lt;a href=&quot;http://www.cs.txstate.edu/courses/courseinfo.php?course_id=CS%205329&quot;&gt;Algorithm Design and Analysis&lt;/a&gt; section of the &lt;a href=&quot;http://www.cs.txstate.edu/graduate_program/comps/&quot;&gt;Texas State University Computer Science graduate comprehensive examination&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;h4&gt;Sorting Algorithms&lt;/h4&gt;
            
&lt;h5&gt;Quick Reference&lt;/h5&gt;

&lt;p&gt;Here is a quick summary of the features offered by some of the most important sorting algorithms.&lt;/p&gt;

&lt;table border=&quot;2&quot;&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Algorithm&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Worst Case&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Average Case&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;In Place?&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Stable?&lt;/b&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Quick Sort&lt;/td&gt;
  &lt;td&gt;n&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;
  &lt;td&gt;n lg n&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Merge Sort&lt;/td&gt;
  &lt;td&gt;n lg n&lt;/td&gt;
  &lt;td&gt;n lg n&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Heap Sort&lt;/td&gt;
  &lt;td&gt;n lg n&lt;/td&gt;
  &lt;td&gt;n lg n&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Insertion Sort&lt;/td&gt;
  &lt;td&gt;n&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;
  &lt;td&gt;n + d&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Counting Sort&lt;/td&gt;
  &lt;td&gt;n + k&lt;/td&gt;
  &lt;td&gt;n + k&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
 &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The table above uses several variables.  The variable n represents the number of items to be sorted.  The variable d represents the number of inversions required by the algorithm.  The variable k represents an upper bound on the values to be sorted.  &lt;/p&gt; 
            
&lt;h5&gt;Quick Sort&lt;/h5&gt;

&lt;p&gt;Quick sort is a classic divide-and-conquer algorithm in which the input array is split into left and right subsets such that all elements in the left subset are &amp;lt;= a pivot value and all elements in the right subset are &amp;gt;= a pivot value.&lt;/p&gt;

&lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;Quicksort(A,p,r)
  if (p&amp;lt;r)
    q = Partition(A,p,r);
    Quicksort(A,p,q-1);
    Quicksort(A,q+1,r);

Partition(A,p,r)
  x = A[r];
  i = p-1;
  for j = p to r-1
    if A[j] &amp;lt;= x
      i++;
      swap(A[i],A[j]);
  i++;
  swap(A[i], A[r]);
  return i;
&lt;/pre&gt;
    
 
&lt;p&gt;To achieve the best-case run time for quick sort, the partition function must evenly divide the input array each time that it is called.  T(n) = 2T(n/2) + O(n) --&amp;gt; T(n) is O(n lg n)&lt;/p&gt;

&lt;p&gt;In the worst-case runtime for the algorithm, each call to the partition function creates sets of size n-1 and 1.  T(n) = T(n-1) + T(1) + O(n) --&amp;gt; T(n) = O(n2)&lt;/p&gt;
            
&lt;h5&gt;Merge Sort&lt;/h5&gt;

&lt;p&gt;Merge sort is also a divide-and-conquer algorithm.  The algorithm relies on the fact that fewer steps are required to construct a sorted list from two sorted lists than two unsorted lists.&lt;/p&gt;

&lt;p&gt;In the merge sort algorithm, unsorted lists are recursively divided in half until they can be divided no further.  At that point, the ordered lists are merged together, forming ever-larger ordered lists.&lt;/p&gt;
            
&lt;h5&gt;Heap Sort&lt;/h5&gt;

&lt;p&gt;Heaps are complete binary trees (with possible exception of rightmost nodes on the lowest level) in which all non-root nodes observe the heap property: parent(i) &amp;gt;= i.
Heap sort operates by building a heap from the input elements and then iteratively removing the top element from the heap.&lt;/p&gt;
            
&lt;h5&gt;Insertion Sort&lt;/h5&gt;

&lt;p&gt;Insertion sort is an easy to implement comparison sort that builds a sorted array one element at a time.  The first k iterations of the algorithm produce an ordered k-element sub-list.  The algorithm requires n such iterations, each of which may need to perform k comparisons in the worst case.&lt;/p&gt;

&lt;p&gt;Insertion sort has good performance on an almost-sorted input list.  Despite poor worst-case performance of the algorithm, it can out-perform other more sophisticated comparison sorting algorithms when operating on very small input sets.&lt;/p&gt;
   
&lt;h5&gt;Counting Sort&lt;/h5&gt;

&lt;p&gt;Counting sort is NOT a comparison sort.  Counting sort takes an input of n integers whose values range from 1 to k.  The general strategy for each input element x is to determine the number of inputs &amp;lt;= x and then put x directly into the correct output position.&lt;/p&gt;
   
&lt;h4&gt;Solving Recurrences&lt;/h4&gt;
            
&lt;h5&gt;Useful Mathematical Properties&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Summation of 1..n = n(n+1)/2&lt;/li&gt;
 &lt;li&gt;x = log&lt;sub&gt;a&lt;/sub&gt; y  --&amp;gt;   (a to some power x equals y)   --&amp;gt;    y = a&lt;sup&gt;x&lt;/sup&gt;&lt;/li&gt;
 &lt;li&gt;log&lt;sub&gt;a&lt;/sub&gt; a = 1&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Asymptotic Notation&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Big-Oh - An upper bound: &lt;br/&gt;  
  f is &amp;#927;(g) if for some c and n&lt;sub&gt;0&lt;/sub&gt;, 0 &amp;lt;= f(n) &amp;lt;= c * g(n) for all values of n &amp;gt;= n&lt;sub&gt;0&lt;/sub&gt;&lt;/li&gt;
 &lt;li&gt;Big-Omega - A lower bound: &lt;br/&gt; 
  f is &amp;#937;(g) if for some c and n&lt;sub&gt;0&lt;/sub&gt;, 0 &amp;lt;= c * g(n) &amp;lt;= f(n) for all values of n &amp;gt;= n&lt;sub&gt;0&lt;/sub&gt;&lt;/li&gt;
 &lt;li&gt;Big-Theta - An asymptotically tight bound: &lt;br/&gt; 
  f is &amp;#920;(g) if for some c&lt;sub&gt;1&lt;/sub&gt;, c&lt;sub&gt;2&lt;/sub&gt; and n&lt;sub&gt;0&lt;/sub&gt;, 0 &amp;lt;= c&lt;sub&gt;1&lt;/sub&gt; * g(n) &amp;lt;= f(n) &amp;lt;= c&lt;sub&gt;2&lt;/sub&gt; * g(n) for all values of n &amp;gt;= n&lt;sub&gt;0&lt;/sub&gt;&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Recursion Trees&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Each node in the tree is labeled with its complexity (excluding recursive calls).&lt;/li&gt;
 &lt;li&gt;The complexity of recursive calls is represented by child nodes in the tree.&lt;/li&gt;
 &lt;li&gt;The total complexity is determined by summing the work done at each level in the tree.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Master Method&lt;/h5&gt;

&lt;p&gt;Many (but not all) recurrences can be solved using the master method.
Consider recurrences of the form: &lt;br/&gt; 
T(n) = a * T(n/b) + f(n)&lt;br/&gt; 
where a &amp;gt;= 1 and b &amp;gt; 1 and f(n) is an asymptotically positive function.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Case 1 - If for some constant e &amp;gt; 0,&lt;br/&gt;f(n) = &amp;#927;(n &lt;sup&gt;(log&lt;sub&gt;b&lt;/sub&gt; a - e)&lt;/sup&gt;)&lt;br/&gt;then T(n) = &amp;#920;(n &lt;sup&gt;(log&lt;sub&gt;b&lt;/sub&gt; a)&lt;/sup&gt;)&lt;/li&gt;
 &lt;li&gt;Case 2 - If f(n) = &amp;#920;(n &lt;sup&gt;(log&lt;sub&gt;b&lt;/sub&gt; a)&lt;/sup&gt;)&lt;br/&gt;then T(N) = &amp;#920;(n &lt;sup&gt;(log&lt;sub&gt;b&lt;/sub&gt; a)&lt;/sup&gt; lg n)&lt;/li&gt;
 &lt;li&gt;Case 3 - If for some constant e &amp;gt; 0,&lt;br/&gt;a) f(n) =  &amp;#937;(n &lt;sup&gt;(log&lt;sub&gt;b&lt;/sub&gt; a + e)&lt;/sup&gt;)&lt;br/&gt;&lt;b&gt;and&lt;/b&gt;&lt;br/&gt;b) a * f(n/b) &amp;lt;= c * f(n) for some c &amp;lt; 1&lt;br/&gt;then T(n) =  &amp;#920;(f(n))&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h4&gt;Divide-and-Conquer Techniques&lt;/h4&gt;

&lt;p&gt;Divide-and-conquer is a recursive algorithm design technique in which subproblems are divided until they are small enough to solve directly.  Solutions to subproblems are then combined to solve the problem at-large.&lt;/p&gt;

&lt;p&gt;Divide-and-conquer algorithms have a related recurrence relation that can be used to determine the run time complexity of the algorithm.&lt;/p&gt;

&lt;p&gt;The quick sort algorithm is an example of a divide-and-conquer algorithm. &lt;/p&gt;
          
&lt;h4&gt;Dynamic Programming&lt;/h4&gt;

&lt;h5&gt;Elements of Dynamic Programming&lt;/h5&gt;

&lt;p&gt;Dynamic programming is applicable when subproblems share subsubproblems.  It is typically utilized in solving optimization problems.&lt;/p&gt;

&lt;p&gt;There are four steps to developing a dynamic programming algorithm:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Characterize the structure of an optimal solution.&lt;/li&gt;
 &lt;li&gt;Recursively define the value of an optimal solution.&lt;/li&gt;
 &lt;li&gt;Compute the value of an optimal solution in a bottom-up fashion.&lt;/li&gt;
 &lt;li&gt;Construct an optimal solution from computed information.&lt;/li&gt;
&lt;/ul&gt;
       
&lt;h5&gt;Assembly Line Scheduling - An Example&lt;/h5&gt;

&lt;p&gt;Two lines, each containing n stations.  The problem is to determine which stations to choose from line 1 and which to choose from line 2 in order to minimize the total time through the factory.
&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;We observe that the problem has optimal substructure: The optimal path to station Si,j contains an optimal path to either station S1,j-1 or S2,j-1.&lt;/li&gt;
 &lt;li&gt;Recursive definition: f1[j]  = min(f1[j-1] + a1,j; f2[j-1] + t2,j-1 + a1,j)&lt;/li&gt;
 &lt;li&gt;Compute bottom-up with a table of the following form:
  &lt;table border=&quot;2&quot;&gt;
   &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Station 1&lt;/td&gt;
    &lt;td&gt;Station 2&lt;/td&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;..&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Station n&lt;/td&gt;

   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;line1&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;

   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;line2&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;
    &lt;td&gt;f/l&lt;/td&gt;

   &lt;/tr&gt;
  &lt;/table&gt;
  Where f is the cost to get to that station and l records the line number of the j-1th station we used to achieve the optimal solution.&lt;/li&gt;
 &lt;li&gt;Optimal solution is constructed from table produced in prior step.&lt;/li&gt;
&lt;/ul&gt;
   
&lt;h4&gt;Greedy Strategies&lt;/h4&gt;

&lt;h5&gt;Elements of Greedy Strategies&lt;/h5&gt;

&lt;p&gt;Greedy strategies are a special case of dynamic programming.  In addition to exhibiting optimal substructure, problems that are appropriately solved by a greedy strategy have the &lt;b&gt;greedy choice property&lt;/b&gt;:&lt;/p&gt;

&lt;blockquote&gt;A globally optimal solution can be obtained by making a locally optimal (greedy) choice.&lt;/blockquote&gt;

&lt;p&gt;Greedy algorithms differ from traditional dynamic programming solutions in that they are a top-down strategy.&lt;/p&gt;
       
&lt;h5&gt;Activity Selection - An Example&lt;/h5&gt;

&lt;p&gt;Problem is to select a max size set of mutually compatible activities.  The key to solving with a greedy strategy is to sort activities in order of finish time.  The greedy solution always chooses the first compatible activity (i.e. the one with the earliest finish time).  That solution is greedy in that it maximizes the remaining available time.
&lt;/p&gt; 

&lt;p&gt;Note that the greedy strategy described above is appropriate for soling the activity selection problem because the problem exhibits:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Optimal substructure&lt;/li&gt;
 &lt;li&gt;Greedy choice property&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Coin Changing - An Example&lt;/h5&gt;

&lt;p&gt;The coin changing problem highlights the fact that greedy strategies are &lt;b&gt;not&lt;/b&gt; always optimal.  In that problem, we are asked to produce the minimal number of coins representing a dollar amount.&lt;/p&gt;

&lt;p&gt;By way of example, consider the scenario in which we are asked to compose $0.31 from these available denominations: $0.25, $0.10, $0.01.  In that case, the Greedy solution would be:&lt;br/&gt;25,1,1,1,1,1,1&lt;br/&gt;However, the optimal solution is:&lt;br/&gt; 10,10,10,1&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/8336796896616892857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-algorithm-design-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/8336796896616892857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/8336796896616892857'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-algorithm-design-and.html' title='Course Notes -- Algorithm Design and Analysis (CS5329)'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-7163787475994870117</id><published>2010-11-28T15:22:00.018-06:00</published><updated>2010-12-05T11:52:12.613-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="data bases"/><category scheme="http://www.blogger.com/atom/ns#" term="normalization"/><category scheme="http://www.blogger.com/atom/ns#" term="notes"/><title type='text'>Course Notes -- Data Base Theory and Design (CS5332)</title><content type='html'>&lt;p&gt;This week I&#39;m revisiting some old course notes that I originally published on &lt;a href=&quot;http://www.big-oh.net&quot;&gt;www.big-oh.net&lt;/a&gt;.  I&#39;m moving away from self-hosting content on that domain, migrating blog-style content into the cloud ... &lt;a href=&quot;http://computergoboom.blogspot.com/&quot;&gt;Blogger&lt;/a&gt; in this case.&lt;/p&gt;

&lt;p&gt;Following are notes that I used to study for the &lt;a href=&quot;http://www.cs.txstate.edu/courses/courseinfo.php?course_id=CS%205332&quot;&gt;Data Base Theory and Design&lt;/a&gt; section of the &lt;a href=&quot;http://www.cs.txstate.edu/graduate_program/comps/&quot;&gt;Texas State University Computer Science graduate comprehensive examination&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;
&lt;h4&gt;Elementary DBMS Concepts&lt;/h4&gt;

&lt;h5&gt;Functional Dependencies, Attributes and Keys&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;A database management system (DBMS) promotes data integrity through elimination of data repetition, referential integrity and transactional operations.&lt;/li&gt;
 &lt;li&gt;An attribute B has a functional dependency on attribute A (A -&amp;gt; B) if for each value of attribute A there is exactly one value of attribute B.&lt;/li&gt;
 &lt;li&gt;A super key is a collection of attributes that uniquely identifies a row in a table -- i.e. the set of attributes in the table is functionally dependent on the super key.&lt;/li&gt;
 &lt;li&gt;A candidate key is a minimal super key.&lt;/li&gt;
 &lt;li&gt;A primary key is selected from all possible candidate keys.&lt;/li&gt;
 &lt;li&gt;A non-prime attribute is one that is not part of any candidate key.&lt;/li&gt;
&lt;/ul&gt;
     
&lt;h4&gt;Normalization of Tables&lt;/h4&gt;
    
&lt;h5&gt;1NF, 2NF, 3NF, and BCNF&lt;/h5&gt;

&lt;ul&gt; 
 &lt;li&gt;A table with a unique key is in first normal form (1NF).  All tables with a primary key are, by definition, in 1NF.&lt;/li&gt;
 &lt;li&gt;A 1NF table is in second normal form (2NF) if all functional dependencies of non-prime attributes depend on a complete candidate key (or another non-prime attribute).  If a non-prime attribute has a functional dependency on a proper subset of a candidate key, then the table is not 2NF.  Note that if no candidate keys are composite, then the table is 2NF by definition.&lt;/li&gt;
 &lt;li&gt;For example, in an EMPLOYEE_SKILLS entity comprised of (EMPLOYEE_ID, EMPLOYEE_ADDRESS, SKILL), the EMPLOYEE_ADDRESS is functionally dependent on EMPLOYEE_ID, which is a proper subset of the only candidate key (EMPLOYEE_ID, SKILL).  This is an intuitively undesirable situation because the EMPLOYEE_ADDRESS attribute will contain repetitive data that may become inconsistent due to update anomalies.&lt;/li&gt;
 &lt;li&gt;A 2NF table is in third normal form (3NF) if all non-prime attributes are non-transitively dependent on every candidate key.  As with 2NF, 3NF protects against logical inconsistencies brought on by update anomalies.&lt;/li&gt;
 &lt;li&gt; BNCF is a slightly stronger version of 3NF in which for all non-trivial functional dependencies A -&amp;gt; B, A must be a super key.
 Most 3NF and BCNF tables are free of update, insertion and deletion anomalies.&lt;/li&gt; 
 &lt;li&gt;Normalization protects against three types of data anomalies.&lt;/li&gt;
&lt;/ul&gt;  
       
&lt;h5&gt;Data Anomalies&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Update anomalies may arise when the same information is stored in multiple locations, thus potentially allowing an update to create inconsistent data.&lt;/li&gt;
 &lt;li&gt; Insertion anomalies may arise when two pieces of unrelated information (A and B) are stored together in the same entity, thus potentially leading to a situation in which A cannot be defined in the DB because B does not yet exist in the DB.&lt;/li&gt;
 &lt;li&gt;Deletion anomalies may arise when two pieces of unrelated information (A and B) are stored together in the same entity, thus potentially leading to a situation in which information about A will be (incorrectly) deleted because the last related B has been deleted.&lt;/li&gt;
&lt;/ul&gt;
        
&lt;h4&gt;Entity-Relationship Modeling&lt;/h4&gt;
      
&lt;h5&gt;Diagram Basics&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Entities are typically nouns that are depicted in a rectangle.&lt;/li&gt;
 &lt;li&gt;Relationships are typically verbs that are depicted in a diamond.&lt;/li&gt;
 &lt;li&gt;Both entities and relationships can have attributes, which are depicted in ellipses.  The names of attributes that form an entity&#39;s primary key are underlined.&lt;/li&gt;
 &lt;li&gt;An arrow indicates an &quot;at most one&quot; relationship.&lt;/li&gt;
 &lt;li&gt;A double line indicates mandatory participation.&lt;/li&gt;
 &lt;li&gt;Wikipedia has an &lt;a href=&quot;http://en.wikipedia.org/wiki/Image:ER_Diagram_MMORPG.png&quot;&gt;excellent example&lt;/a&gt; of an entity-relationship diagram.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/7163787475994870117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-data-base-theory-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/7163787475994870117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/7163787475994870117'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-data-base-theory-and.html' title='Course Notes -- Data Base Theory and Design (CS5332)'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-4324503185216545140</id><published>2010-11-28T15:21:00.012-06:00</published><updated>2011-01-16T22:55:46.945-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="notes"/><category scheme="http://www.blogger.com/atom/ns#" term="search"/><title type='text'>Course Notes -- Advanced Artificial Intelligence (CS5346)</title><content type='html'>&lt;p&gt;This week I&#39;m revisiting some old course notes that I originally published on &lt;a href=&quot;http://www.big-oh.net&quot;&gt;www.big-oh.net&lt;/a&gt;.  I&#39;m moving away from self-hosting content on that domain, migrating blog-style content into the cloud ... &lt;a href=&quot;http://computergoboom.blogspot.com/&quot;&gt;Blogger&lt;/a&gt; in this case.&lt;/p&gt;

&lt;p&gt;Following are notes that I used to study for the &lt;a href=&quot;http://www.cs.txstate.edu/courses/courseinfo.php?course_id=CS%205346&quot;&gt;Advanced Artificial Intelligence&lt;/a&gt; section of the &lt;a href=&quot;http://www.cs.txstate.edu/graduate_program/comps/&quot;&gt;Texas State University Computer Science graduate comprehensive examination&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;h4&gt;Conventional Search&lt;/h4&gt;

&lt;h5&gt;Quick Reference&lt;/h5&gt;

&lt;p&gt;Conventional search strategies utilize only the facts provide in the problem definition.  They are dumb searches in the sense that they are only capable of generating successors and distinguishing goal states from non-goal states.&lt;/p&gt;

&lt;p&gt;Here is a quick summary of the features offered by some of the most important conventional search strategies.&lt;/p&gt;

&lt;table border=&quot;2&quot;&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Strategy&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Complete?&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Optimal?&lt;/b&gt;&lt;/td&gt;
  &lt;td&gt;&lt;b&gt;Space&lt;/b&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Breadth First Search&lt;/td&gt;
  &lt;td&gt;Uses a queue to manage successor nodes.&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;&amp;#927;(b&lt;sup&gt;d+1&lt;/sup&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Depth First Search&lt;/td&gt;
  &lt;td&gt;Uses a stack to manage successor nodes.&lt;/td&gt;
  &lt;td&gt;No (when the search space is infinitely deep)&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
  &lt;td&gt;&amp;#927;(bm)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Depth Limited Search&lt;/td&gt;
  &lt;td&gt;A derivation of depth first search that treats nodes at some cutoff maximum depth as though they had no successors.&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
  &lt;td&gt;No&lt;/td&gt;
  &lt;td&gt;&amp;#927;(bl)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Iterative Deepening Depth Limited Search&lt;/td&gt;
  &lt;td&gt;Iteratively runs depth limited search with increasing cutoff values until a goal state is found.&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;Yes&lt;/td&gt;
  &lt;td&gt;&amp;#927;(bd)&lt;/td&gt;
 &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The table above uses several variables.  The variable b represents the branching factor of the search space.  The variable d represents the depth of the shallowest solution in the search space.  The variable m represents the maximum depth of the search tree.&lt;/p&gt; 
            
&lt;h4&gt;Informed Search&lt;/h4&gt;
   
&lt;h5&gt;Best-First Strategies&lt;/h5&gt;

&lt;p&gt;Informed searches use problem-specific knowledge to find solutions (goal states) more efficiently.  An important subclass of informed searches, best-first searches navigate the search space by choosing the next (best) node for expansion based on an evaluation function.  The efficiency of a best-first search algorithm depends entirely on the accuracy of the evaluation function -- i.e. how often it can recommend the node that is next in leading us to a goal state.  There are many best-first search algorithms, differing only in the evaluation functions that they use.&lt;/p&gt;

&lt;p&gt;A priority queue is useful data structure in implementing best-first search algorithms.&lt;/p&gt;
 
&lt;h5&gt;Greedy Best-First Search&lt;/h5&gt;

&lt;p&gt;The greedy best-first search strategy uses the evaluation function f(n) = h(n), where h(n) is a heuristic that judges how close the current node is to a goal state.  Solutions found by this evaluation strategy may not be optimal.  Moreover, the strategy is not complete.&lt;/p&gt;
            
&lt;h5&gt;A* Search&lt;/h5&gt;

&lt;p&gt;The A* search strategy is a best-first search strategy that uses the evaluation function f(n) = g(n) + h(n), where g(n) is the cost to get to the current node and h(n) is a heuristic estimate of the cost from the current node to a goal state.  If h(n) is an admissible heuristic, then A* is both complete and optimal.  An admissible heuristic is one that never overestimates the cost to reach a goal state.
&lt;/p&gt;  
&lt;p&gt;Problem relaxation and combination are both important methods for developing admissible heuristics for the A* search strategy.&lt;/p&gt;
            
&lt;h4&gt;Local Search&lt;/h4&gt;
       
&lt;h5&gt;Overview&lt;/h5&gt;

&lt;p&gt;Local search strategies can be used when we seek only a goal state, but not a path to the goal state.  In general, local search algorithms operate by starting with start with a goal state and then moving to a neighbor state.  Local search strategies typically use much less memory than both the conventional and informed search methods described in the sections above.&lt;/p&gt;
   
&lt;h5&gt;Examples&lt;/h5&gt;

&lt;p&gt;Here is a list of some important local search strategies.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  Hill climbing is the most basic local search technique.  In hill climbing, we iteratively move to neighbor states with greater value until we hit a local maximum.
 &lt;/li&gt;
 &lt;li&gt;
  Random-restart hill climbing performs the hill climbing algorithm several times from random starting states.
 &lt;/li&gt;
 &lt;li&gt;
  In simulated annealing, the strategy is to pick a random successor move.  If the move is an improvement, it is kept.  Otherwise, if the move is not an improvement, it is only kept with some probability less than 100%.
 &lt;/li&gt;
&lt;/ul&gt;
   
&lt;h4&gt;Minimax Adversarial Search&lt;/h4&gt;

&lt;h5&gt;Overview&lt;/h5&gt;

&lt;p&gt;The minimax search strategy seeks to minimize the maximum possible loss a player will incur when playing a turn-based multiplayer game.  The minimax search strategy assumes that the opposing player will always make optimal moves.  The strategy also relies on having a utility function that can be used to score game states as well as a terminal-test function that can be used to identify terminal game states.&lt;/p&gt;

&lt;p&gt;We typically describe the players of the game as A (who is trying to maximize the score) and B (who is trying to minimize the score.  At each step in the minimax search tree, we assume that A and B make optimal choices, meaning that A selects the child with the largest score and B selects the child with the smallest score.&lt;/p&gt;
   
&lt;h5&gt;Example&lt;/h5&gt;

&lt;p&gt;Wikipedia has an excellent example of a 2-ply minimax search tree in which circles represent &quot;A&#39;s turn&quot; and squares represent &quot;B&#39;s turn.&quot;  Notice that circles (A) are filled-in with the largest child value and squares (B) are filled-in with the smallest child value.&lt;/p&gt;   
    
&lt;h5&gt;Pseudo Code&lt;/h5&gt;

&lt;p&gt;The implementation of the minimax search strategy is very simple, requiring only two nearly identical recursive control functions:&lt;/p&gt;
        
&lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;function MaxValue(state) returns a utility value
 if Terminal-State(state) 
  return Utility(state); 
 v = -infinity;
 for s in Successors(state) 
  v = Max(v, MinValue(s));
 return v;
 
function MinValue(state) returns a utility value
 if Terminal-State(state)
  return Utility(state);
 v = +infinity;
 for s in Successsors(state)
  v = Min(v, MaxValue(s));
 return v;
&lt;/pre&gt;
    
&lt;h5&gt;Alpha-Beta Pruning&lt;/h5&gt;

&lt;p&gt;Alpha-Beta pruning is a technique that allows us to calculate a correct minnimax decision without considering every node in the game tree.  Specifically, alpha-beta pruning trims away sub trees that cannot possibly influence the final value calculated by the minimax search strategy.&lt;/p&gt; 
 
&lt;p&gt;To apply the alpha-beta pruning concept to our minimax functions, we need only introduce two new parameters to the pseudo-code cataloged above:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;a - the best (largest) value in the search path for Max&lt;/li&gt;
 &lt;li&gt;b - the best (smallest) value in the search path for Min&lt;/li&gt;
&lt;/ul&gt;
        
&lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;function MaxValue(state, a, b) returns a utility value
 if Terminal-State(state) 
  return Utility(state);
 v = -infinity;
 for s in Successors(state) 
  v = Max(v, MinValue(s, a, b));
  if v &gt;= b
   return v;
  else
   a = Max(a, v);
 return v;
function MinValue(state, a, b) returns a utility value
 if Terminal-State(state)
  return Utility(state);
 v = +infinity;
 for s in Successsors(state)
  v = Min(v, MaxValue(s, a, b));
  if v &amp;lt;= a
   return v;
  else
   b = Min(b, v);
 return v;
&lt;/pre&gt;
    
&lt;h5&gt;Imperfect Search&lt;/h5&gt;

&lt;p&gt;The minimax search procedure (with or without alpa-beta pruning) is an optimal search strategy.  However, the large search space of most games prohibits execution of the minimax search procedure down to terminal nodes.  In order to search for a good solution to an adversarial problem, an evaluation function can be used to turn non-terminal nodes into terminal nodes.  To conduct imperfect searches, we must make two modifications to the minimax search routine:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;The utility function is replaced by a heuristic evaluation function.&lt;/li&gt;
 &lt;li&gt;The terminal test is replaced by a cutoff test that decides when to call the evaluation function.&lt;/li&gt;
&lt;/ul&gt;    
       
&lt;h4&gt;Knowledge Representation&lt;/h4&gt;
       
&lt;h5&gt;Motivation&lt;/h5&gt;

&lt;p&gt;Logics (propositional or first-order predicate) are useful for building knowledge bases that can be used by logical agents to infer the answers to submitted problems.  Such systems are generally declarative (as opposed to procedural) and are implemented by inference algorithms that are both sound (truth preserving) and complete.&lt;/p&gt;  
    
&lt;h5&gt;Propositional Logic&lt;/h5&gt;

&lt;p&gt;The syntax of propositional logic is characterized by atomic sentences comprised of propositional symbols (e.g. R P Q), negations (-), conjunctions (^), disjunctions (or), implications (-&amp;gt;) and biconditionals (&amp;lt;-&amp;gt;).  Truth tables are one way of defining the meaning of the above operators.&lt;/p&gt;

&lt;p&gt;Propositional sentences can be classified according to validity and satisfiability:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;A valid proposition is one that is true in every model.&lt;/li&gt;
 &lt;li&gt;A satisfiable proposition is one that is true in some model.&lt;/li&gt;
 &lt;li&gt;A non-satisfiable proposition is one that is true in no model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inference rules can be applied to propositional sentences to soundly derive new sentences.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  Modus Ponens:&lt;br/&gt; 
  * a-&amp;gt;b&lt;br/&gt;
  * a&lt;br/&gt;
  entails b
 &lt;/li&gt;
 &lt;li&gt;

  And-Elimination:&lt;br/&gt; 
  * a ^ b&lt;br/&gt; 
  entails a&lt;br/&gt;
 &lt;/li&gt;
 &lt;li&gt;
  Unit Resolution:&lt;br/&gt; 
  * a or b&lt;br/&gt;
  * -b&lt;br/&gt;

  entails a&lt;br/&gt;
 &lt;/li&gt;
 &lt;li&gt;
  Resolution:&lt;br/&gt; 
  * a or b&lt;br/&gt;
  * -b or c&lt;br/&gt; 
  entails a or c&lt;br/&gt;

 &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Horn clauses are propositional logic clauses that are limited to being disjunctions of literals, of which at most one is positive.  Every Horn clause can be rewritten as an implication.  For example, the Horn clause (-a or -b or c) can be rewritten as the implication a ^ b -&amp;gt; c.  Horn clauses support forward chaining and backward chaining.&lt;/p&gt;

&lt;p&gt;Another standard format for propositional logic sentences is conjunctive normal form.  All propositional logic sentences can be translated to conjunctive normal form, which is a conjunction of disjunctions: (A or -B or C) ^ (-D or E) ^ (F or G or H)&lt;/p&gt;

&lt;p&gt;De Morgan&#39;s laws are useful when converting to CNF:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;-(A ^ B) can be rewritten as (-A or -B)&lt;/li&gt;
 &lt;li&gt;-(A or B) can be rewritten as (-A ^ -B)&lt;/li&gt;
&lt;/ul&gt;
    
&lt;h5&gt;First-Order Predicate Logic&lt;/h5&gt;

&lt;p&gt;Propositional logic is not sufficient to succinctly represent complex environments.  First-order predicate logic is more powerful because it deals with objects and their relations, not just propositional facts.  The syntax of first-order predicate logic is comprised of:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Constants, which stand for objects -- e.g. John&lt;/li&gt;
 &lt;li&gt;Predicates, which stand for relations -- e.g. Brother(John, Tom)&lt;/li&gt;
 &lt;li&gt;Functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First-order predicate logic also allows the use of the logical connectives we saw in propositional logic: ^, V, -, -&amp;gt;, &amp;lt;-&amp;gt;.  In addition, first-order predicate logic also allows the use of quantifiers, which allow us to make single statements that apply to collections of objects.  The universal quantifier (&amp;#8704;) and the existential quantifier (&amp;#8707;) can be used to rewrite multiple propositional logic sentences as a single first-order predicate logic sentence.  For example, we can capture the idea that &quot;everyone loves someone&quot; using this first-order predicate logic sentence: &amp;#8704;x &amp;#8707;y Loves(x,y)&lt;/p&gt;
   
&lt;h4&gt;Expert Systems&lt;/h4&gt;

&lt;p&gt;The techniques of forward chaining and backward chaining can both be used to construct expert systems.&lt;/p&gt;
    
&lt;h5&gt;Forward Chaining&lt;/h5&gt;

&lt;p&gt;Forward chaining is an example of data-driven reasoning -- i.e. reasoning in which the focus of attention begins with all known facts.&lt;/p&gt;

&lt;p&gt;The forward chaining algorithm seeks to determine whether a query q is entailed by the (Horn clause) sentences in a knowledge base.  Forward chaining begins by collecting all of the know facts (positive literals) in the database.  Next, using implication, if all premises of a knowledge base sentence are known, its conclusion is added to the collection of facts.  That process is repeated until either the query q is derived as a fact or until no further facts can be generated.&lt;/p&gt;
   
&lt;h5&gt;Backward Chaining&lt;/h5&gt;

&lt;p&gt;Backward chaining is an example of goal-directed reasoning -- i.e. reasoning in which the focus of attention begins with the query statement.&lt;/p&gt;

&lt;p&gt;The backward chaining algorithm works backward from the query statement.  The algorithm attempts to prove true a set of statements from which the query q is entailed.  For each statement s needed to entail q, backward chaining is recursively applied to prove s.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/4324503185216545140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-advanced-artificial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/4324503185216545140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/4324503185216545140'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-advanced-artificial.html' title='Course Notes -- Advanced Artificial Intelligence (CS5346)'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-3088536931046972590</id><published>2010-11-28T15:20:00.006-06:00</published><updated>2010-12-25T01:18:28.908-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="lifecycle"/><category scheme="http://www.blogger.com/atom/ns#" term="notes"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Course Notes -- Survey of Software Engineering (CS5391)</title><content type='html'>&lt;p&gt;This week I&#39;m revisiting some old course notes that I originally published on &lt;a href=&quot;http://www.big-oh.net&quot;&gt;www.big-oh.net&lt;/a&gt;.  I&#39;m moving away from self-hosting content on that domain, migrating blog-style content into the cloud ... &lt;a href=&quot;http://computergoboom.blogspot.com/&quot;&gt;Blogger&lt;/a&gt; in this case.&lt;/p&gt;

&lt;p&gt;Following are notes that I used to study for the &lt;a href=&quot;http://www.cs.txstate.edu/courses/courseinfo.php?course_id=CS%205391&quot;&gt;Survey of Software Engineering&lt;/a&gt; section of the &lt;a href=&quot;http://www.cs.txstate.edu/graduate_program/comps/&quot;&gt;Texas State University Computer Science graduate comprehensive examination&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;h4&gt;Software Development Lifecycle Models&lt;/h4&gt;

&lt;h5&gt;Waterfall Model&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;This model is document-driven and is also known as the &quot;linear sequential&quot; model.&lt;/li&gt;
 &lt;li&gt;Activities in this model are structured in a linear cascade of phases in which the output of the previous phase is the input to the next phase.&lt;/li&gt;
 &lt;li&gt;Phases are: Feasibility Study -&amp;gt; Requirements Analysis -&amp;gt; Technical Design -&amp;gt; Code and Unit Test -&amp;gt; Integration and System Test -&amp;gt; Deployment and Maintenance.&lt;/li&gt;
 &lt;li&gt;The linear structure of this model provides no feedback to prior phases.  This is often impractical since, for example, it is not always possible to identify all requirements at the beginning of a project.&lt;/li&gt;
&lt;/ul&gt;
    
&lt;h5&gt;Incremental Model&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;The stages of this model consist of expanding increments of an operational software product.&lt;/li&gt;
 &lt;li&gt;Increments are delivered to customers as they are completed.&lt;/li&gt;
 &lt;li&gt;Each delivered unit is a self-contained functional unit.&lt;/li&gt;
 &lt;li&gt;This methodology allows for continuous validation (as opposed to a final validation phase).&lt;/li&gt;
 &lt;li&gt;This model retains all steps defined in the waterfall model, but performs those steps multiple times in an iterative fashion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Spiral Model&lt;/h5&gt;

&lt;p&gt;This model iteratively utilizes the steps below to identify and mitigate high-risk issues in the development of high-quality software.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Step 1 - Identify quality objectives for a portion of the product.&lt;/li&gt;
 &lt;li&gt;Step 2 - Identify risks in achieving objectives and evaluate alternative mitigation strategies.&lt;/li&gt;
 &lt;li&gt;Step 3 - Develop and verify a unit of functionality.&lt;/li&gt;
 &lt;li&gt;Step 4 - Review development results and plan for next iteration.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Capability Maturity Model&lt;/h5&gt;

&lt;p&gt;The Capability Maturity Model (CMM) has the following characteristics:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;The CMM is an application of process management and quality improvement concepts to software development and maintenance.&lt;/li&gt;
 &lt;li&gt;The CMM doesn&#39;t describe how to create an effective software organization.  Rather it simply describes the features of such an organization.&lt;/li&gt;
 &lt;li&gt;The CMM defines an ordinal scale of five levels used to measure the capabilities of an organization&#39;s software process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each level of the CMM is composed of a set of key process areas for which related activities are defined:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Level 1 - Chaotic/Initial.  Processes are unpredictable and poorly controlled.  Success results from individual efforts.&lt;/li&gt;
 &lt;li&gt;Level 2 - Repeatable.  Projects can repeat previously mastered tasks.  Basic project management processes are established to track cost, schedule and functionality.&lt;/li&gt;
 &lt;li&gt;Level 3 - Defined.  Processes are defined and understood by staff.  The software process activities are standardized and documents.&lt;/li&gt;
 &lt;li&gt;Level 4 - Managed.  Processes are measured and controlled (since you can only manage what you can measure).&lt;/li&gt;
 &lt;li&gt;Level 5 - Optimized.  Organization is focused on process improvement.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h4&gt;Software Design Methodologies&lt;/h4&gt;
    
&lt;h5&gt;Structured Analysis and Design&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Structured analysis and design attempts to harness complexity through a hierarchical design created by iteratively decomposing program segments until the program is completed.&lt;/li&gt;
 &lt;li&gt;The algorithm is the fundamental building block of this design methodology.&lt;/li&gt;
 &lt;li&gt;Abstraction is used to focus on subproblems, ignoring the overall strategy of the algorithm.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Object-Oriented Analysis and Design&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Classes and objects are the fundamental building blocks of this design methodology; they are extracted from the vocabulary of the problem domain.&lt;/li&gt;
 &lt;li&gt;Abstraction is applied to reuse the features of related classes that are already part of the object model.&lt;/li&gt;
 &lt;li&gt;Reuse is enabled by language features: inheritance and polymorphism.&lt;/li&gt;
&lt;/ul&gt;
   
&lt;h4&gt;Software Testing Strategies&lt;/h4&gt;
            
&lt;h5&gt;Program Inspection&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Goal: Ensure the program element follows the specification.  Ensure the program element supports stated non-functional requirements.&lt;/li&gt;
 &lt;li&gt;Method: A review group (comprising the roles of Moderator, Author, Reviewer and Recorder), uses a checklist to review a program elements to ensure the above goals.&lt;/li&gt;
 &lt;li&gt;Phase: Implementation.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Black-Box Testing&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Goal: Verify that a system or sub-system behaves as expected.&lt;/li&gt;
 &lt;li&gt;Method: Derive test cases from the public interface specification.  May use equivalence partitioning and boundary value analysis strategies.&lt;/li&gt;
 &lt;li&gt;Phase: System and Integration Testing.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;White-Box Testing&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Goal: Verify that a software unit behaves as expected.&lt;/li&gt;
 &lt;li&gt;Method: Derive test cases from the internal structure of the program.&lt;/li&gt;
 &lt;li&gt;Phase: Implementation.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Load or Stress Testing&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Goal: Gain confidence that software meets non-functional performance requirements.&lt;/li&gt;
 &lt;li&gt;Method: Find mean time to failure using an input set that is appropriately varied.&lt;/li&gt;
 &lt;li&gt;Phase: Integration Testing.&lt;/li&gt;
&lt;/ul&gt;
            
&lt;h5&gt;Regression Testing&lt;/h5&gt;

&lt;ul&gt;
 &lt;li&gt;Goal: Ensure that previously released features have not been broken by new software updates.&lt;/li&gt;
 &lt;li&gt;Method: Execute functional test cases to gain confidence that key software features have not been broken.&lt;/li&gt;
 &lt;li&gt;Phase: Maintenance.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/3088536931046972590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-survey-of-software.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/3088536931046972590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/3088536931046972590'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/11/course-notes-survey-of-software.html' title='Course Notes -- Survey of Software Engineering (CS5391)'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-7302830223792530468</id><published>2010-11-07T23:32:00.006-06:00</published><updated>2011-01-16T22:54:42.168-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Servlet"/><title type='text'>Logging HttpServletRequests</title><content type='html'>&lt;h4&gt;Motivation&lt;/h4&gt;

&lt;p&gt;Whereas &lt;a href=&quot;http://computergoboom.blogspot.com/2010/10/observing-httpservletresponses.html&quot;&gt;observing ServletResponses&lt;/a&gt; is non-trivial, &lt;strike&gt;Sun&lt;/strike&gt; Oracle makes it much easier to observe HTTP requests via the &lt;a href=&quot;http://download.oracle.com/javaee/6/api/javax/servlet/ServletRequestListener.html&quot;&gt;ServletRequestListener&lt;/a&gt; interface. ServletRequestListeners are awesome; they make it super easy to record and log requests, thereby improving the &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_quality#Understandability&quot;&gt;undestandability&lt;/a&gt; of your web applications. Recording and logging ServletRequests with a listener is preferable to doing that same work in the requested resource (Servlet, JSP, etc.) since the former strategy achieves an improved &lt;a href=&quot;http://en.wikipedia.org/wiki/Separation_of_concerns&quot;&gt;separation of concerns&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Implementation&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/index.html&quot;&gt;Big-Oh Software&#39;s CommonWeb Framework&lt;/a&gt; provides &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/listener/request/RequestObserverListener.html&quot;&gt;RequestObserverListener&lt;/a&gt;, an abstract implementation of the ServletRequestListener interface that can be extended to observe ServletRequests in myriad meaningful ways.  That abstract implementation of the listener interface collaborates with the &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/listener/request/ObservedHttpServletRequest.html&quot;&gt;ObservedHttpServletRequest&lt;/a&gt; class, which adapts an original ServletRequest into an object that is more easily observed, recorded and logged.&lt;/p&gt;

&lt;h4&gt;An Example: Servlet Request Logging&lt;/h4&gt;

&lt;p&gt;Using the &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/listener/request/RequestObserverListener.html&quot;&gt;RequestObserverListener&lt;/a&gt; to log incoming Servlet requests is shamefully easy.  Only a few lines of Java and XML are needed:&lt;/p&gt;

&lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;
package foo.bar;

import net.big_oh.common.web.listener.request.*;

public class MyRequestLoggerListener extends RequestObserverListener
{

 @Override
 protected void doOnServletRequestInitialized(ObservedServletRequest observedServletRequest)
 {
  System.out.println(observedServletRequest);
 }

}
&lt;/pre&gt;

... and ...

&lt;pre class=&quot;brush: xml; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;!-- web.xml snippet --&amp;gt;

&amp;lt;listener&amp;gt;
  &amp;lt;listener-class&amp;gt;foo.bar.RequestLoggerListener&amp;lt;/listener-class&amp;gt;
&amp;lt;/listener&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
By applying the above logging listener to a web application, you&#39;ll see that new ServletRequests are logged in this format:
&lt;br/&gt;
&lt;i&gt;Received a HTTP/1.1 request from localhost (127.0.0.1) for resource http://127.0.0.1:8080/CommonWeb/ (GET) -- jSessionId: B46435C89F9FABCE571AF701E0BC6820 -- userName: unknown&lt;/i&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/7302830223792530468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/11/logging-httpservletrequests.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/7302830223792530468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/7302830223792530468'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/11/logging-httpservletrequests.html' title='Logging HttpServletRequests'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-206056122738093091</id><published>2010-10-17T18:54:00.005-05:00</published><updated>2011-01-16T22:50:02.529-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Filter"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Servlet"/><title type='text'>Observing HttpServletResponses</title><content type='html'>&lt;h4&gt;Motivation&lt;/h4&gt;

&lt;p&gt;
 &lt;a href=&quot;http://download-llnw.oracle.com/javaee/6/api/javax/servlet/Filter.html&quot;&gt;Filters&lt;/a&gt; are a great way to observe (or even modify) the response generated for an HTTP request.  This post will present a handy application of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;observer pattern&lt;/a&gt; from within a Java web &lt;a href=&quot;http://download-llnw.oracle.com/javaee/6/api/javax/servlet/Filter.html&quot;&gt;Filter&lt;/a&gt;, allowing developers to monitor responses to HTTP requests as they are constructed.
&lt;/p&gt;

&lt;h4&gt;Implementation&lt;/h4&gt;

&lt;p&gt;
 The response observer filter I want to describe is part of &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/index.html&quot;&gt;Big-Oh Software&#39;s CommonWeb Framework&lt;/a&gt;.  That framework defines a &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/filters/response/ResponseObserver.html&quot;&gt;ResponseObserver&lt;/a&gt; interface that models the events that transpire while constructing the response to an HTTP request.  A simple, abstract filter class, &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/filters/response/ResponseObserverFilter.html&quot;&gt;ResponseObserverFilter&lt;/a&gt;, serves as the base class for (potentially) many filters that observe those events.
&lt;/p&gt;

&lt;h4&gt;An Example: Response Size Monitor Filter&lt;/h4&gt;

&lt;p&gt;
 Because the abstract &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/filters/response/ResponseObserverFilter.html&quot;&gt;ResponseObserverFilter&lt;/a&gt; utilizes the &lt;a href=&quot;http://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;observer pattern&lt;/a&gt;, we can use it to define many useful, concrete filters without having to write much code.  For example, it is quite easy to create a &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/impl/ResponseSizeMonitorFilter.html&quot;&gt;ResponseSizeMonitorFilter&lt;/a&gt; that announces the size of the response generated for an HTTP request.
&lt;/p&gt;

&lt;p&gt;Applying the &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/impl/ResponseSizeMonitorFilter.html&quot;&gt;ResponseSizeMonitorFilter&lt;/a&gt;  to the servlets in your web application is a simple matter of including the snippet below in your web.xml file:&lt;/p&gt;

&lt;pre class=&quot;brush: xml; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;!-- web.xml snippet --&amp;gt;

&amp;lt;filter&amp;gt;
  &amp;lt;filter-name&amp;gt;ResponseSizeMonitorFilter&amp;lt;/filter-name&amp;gt;
  &amp;lt;filter-class&amp;gt;net.big_oh.common.web.impl.ResponseSizeMonitorFilter&amp;lt;/filter-class&amp;gt;
&amp;lt;/filter&amp;gt;

&amp;lt;filter-mapping&amp;gt;
  &amp;lt;filter-name&amp;gt;ResponseSizeMonitorFilter&amp;lt;/filter-name&amp;gt;
  &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
&amp;lt;/filter-mapping&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
 The &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommonWeb/xref/net/big_oh/common/web/impl/ResponseSizeMonitorFilter.html&quot;&gt;ResponseSizeMonitorFilter&lt;/a&gt; will now log the size of HTTP responses in the following format:
 &lt;br/&gt;
 &lt;i&gt;The response for the requested url (http://127.0.0.1:8080/CommonWeb/ImageServlet) contained about 4.09 kilobytes.&lt;/i&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/206056122738093091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/10/observing-httpservletresponses.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/206056122738093091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/206056122738093091'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/10/observing-httpservletresponses.html' title='Observing HttpServletResponses'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-5141349288272010394</id><published>2010-08-01T20:36:00.023-05:00</published><updated>2011-01-16T22:48:14.577-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="productivity"/><category scheme="http://www.blogger.com/atom/ns#" term="tools"/><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu"/><title type='text'>Conky</title><content type='html'>&lt;h4&gt;Introducing Conky&lt;/h4&gt;

&lt;div&gt;

 &lt;div style=&quot;float: right;&quot;&gt;
  &lt;img style=&quot;cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkXbZ3vSiuv-F2jhWAFw2p0WPhMeCN3e5NFgnqssNFjfaBnRRMiKznmAYbctiN9dOXJDVC9mbtccuZLvKE0DdsFwOeiNT8_9o4YNxM0jq7Av7ndDwq6IV_z4a5GpQ4vKC4jcPD-zhxEis/s400/conkyDesktop.png&quot; alt=&quot;conky desktop image&quot; id=&quot;BLOGGER_PHOTO_ID_5500630970238656466&quot; border=&quot;0&quot; /&gt;
 &lt;/div&gt;

 &lt;p&gt;
  Conky is a free tool for embedding information into your X desktop.
  I use it during the work day to keep an eye on my computer&#39;s resources and to help remind me how I should be utilizing my own resources.
 &lt;/p&gt;

 &lt;p&gt;
  This tutorial isn&#39;t designed to teach you how to use Conky.  For that, you&#39;ll have to check out the &lt;a href=&quot;http://conky.sourceforge.net/documentation.html&quot;&gt;Conky documentation&lt;/a&gt;.
  However, this tutorial will show you how to customize Conky to embed information in your Ubuntu desktop, just like the image to the right.
 &lt;/p&gt;

&lt;/div&gt;

&lt;div style=&quot;clear: both;&quot;&gt;&lt;/div&gt;

&lt;h4&gt;Configuring Conky&lt;/h4&gt;

&lt;p&gt;
 Conky is configurable through the .conkyrc file in your home directory.
 In order to get Conky to produce the output shown above, I made a few changes to the standard sample .conkyrc file, which you can find at /usr/share/doc/conky/examples/conkyrc.sample.gz.
&lt;/p&gt;

&lt;p&gt;
 Conky&#39;s colors are highly configurable.  I&#39;ve selected a nice earthy palette of yellow, orange and gray.
&lt;/p&gt;
        
&lt;pre class=&quot;brush: text; tab-size: 2; class-name: code&quot;&gt;
# Colors
default_color BDB76B # Values
color0 FF8C00 # Headers
color1 lightgrey # Line Items
color2 BDB76B # Highlighted Values
&lt;/pre&gt;

&lt;p&gt;
 Next I use my newly defined color palette to draw attention to the processes that are currently consuming the most cpu and memory resources on my computer.
&lt;/p&gt;
        
&lt;pre class=&quot;brush: text; tab-size: 2; class-name: code&quot;&gt;
${color1} ${top name 1} ${top pid 1} ${color2}${top cpu 1}${color1} ${top mem 1}
...

${color1} ${top_mem name 1} ${top_mem pid 1} ${top_mem cpu 1} ${color2}${top_mem mem 1}
&lt;/pre&gt;
    
&lt;p&gt;
 I&#39;ve also asked Conky to embed the contents of a text file into my desktop.
 Specifically, I like to always see my TODO list.
&lt;/p&gt;
        
&lt;pre class=&quot;brush: text; tab-size: 2; class-name: code&quot;&gt;
${color0}TODO:${color1}
${execi 30 cat /home/username/Desktop/TODO.txt | fold -w40 }
&lt;/pre&gt;   

&lt;p&gt;
 Integrating all of the tweaks described above, I arrived at the .conkyrc configuration file cataloged below.
&lt;/p&gt;

&lt;pre class=&quot;brush: text; tab-size: 2; class-name: code&quot;&gt;
################################ Conky Settings ################################

# set to yes if you want Conky to be forked in the background
background no

# X font when Xft is disabled, you can pick one with program xfontsel
font arial

# Use Xft?
use_xft yes

# Xft font when Xft is enabled
xftfont Bitstream Vera Sans Mono:size=11

# Text alpha when using Xft
xftalpha 0.8

# mail spool
mail_spool $MAIL

# Update interval in seconds
update_interval 5.0

# This is the number of times Conky will update before quitting.
# Set to zero to run forever.
total_run_times 0

# Create own window instead of using desktop (required in nautilus)
own_window yes

# If own_window is yes, you may use type normal, desktop or override
own_window_type override

# Use pseudo transparency with own_window?
own_window_transparent yes

# If own_window_transparent is set to no, you can set the background colour here
own_window_colour hotpink

# If own_window is yes, these window manager hints may be used
own_window_hints undecorated,below,sticky

# Use double buffering (reduces flicker, may not work for everyone)
double_buffer yes

# Minimum size of text area
minimum_size 280 5

# Draw shades?
draw_shades no

# Draw outlines?
draw_outline no

# Draw borders around text
draw_borders no

# Draw borders around graphs
draw_graph_borders yes

# Stippled borders?
stippled_borders 8

# border margins
border_margin 4

# border width
border_width 1

# Default border colors
default_shade_color black
default_outline_color black

# Text alignment, other possible values are commented
alignment top_right

# Gap between borders of screen and text
# same thing as passing -x at command line
gap_x 20
gap_y 50

# Subtract file system buffers from used memory?
no_buffers yes

# set to yes if you want all text to be in uppercase
uppercase no

# number of cpu samples to average
# set to 1 to disable averaging
cpu_avg_samples 2

# number of net samples to average
# set to 1 to disable averaging
net_avg_samples 2

# Force UTF8? note that UTF8 support required XFT
override_utf8_locale no

# Add spaces to keep things from moving about? This only affects certain objects.
use_spacer no

# Colors
default_color BDB76B # Values
color0 FF8C00 # Headers
color1 lightgrey # Line Items
color2 BDB76B # Highlighted Values

################################ Screen Text ################################

TEXT
$nodename - $sysname $kernel on $machine
$hr
${color0}Summary:$color
${color1}IP:$color ${addr eth0} ${alignr}${color1}Uptime:$color $uptime_short

${color1}CPU Usage:$color $cpu% ${cpubar}
${color1}RAM Usage:$color $mem/$memmax - $memperc% ${membar}
${color1}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar}
$color$hr

${color0}File Systems:$color
/ $color${fs_used /}/${fs_size /} ${fs_bar /}
$color$hr
${color} Name             PID     CPU%   MEM%
${color0}Top CPU:$color
${color1} ${top name 1} ${top pid 1} ${color2}${top cpu 1}${color1} ${top mem 1}

${color1} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2}
${color1} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3}
${color1} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4}
${color0}Top Mem:$color

${color1} ${top_mem name 1} ${top_mem pid 1} ${top_mem cpu 1} ${color2}${top_mem mem 1}
${color1} ${top_mem name 2} ${top_mem pid 2} ${top_mem cpu 2} ${top_mem mem 2}
${color1} ${top_mem name 3} ${top_mem pid 3} ${top_mem cpu 3} ${top_mem mem 3}
${color1} ${top_mem name 4} ${top_mem pid 4} ${top_mem cpu 4} ${top_mem mem 4}

$hr
${color0}Network Connections:$color ${tcp_portmon 1 65535 count}
$color Inbound Ports: ${tcp_portmon 1 32767 count}  Outbound Ports: ${tcp_portmon 32768 61000 count}
${color0}Outbound Connection ${alignr} Remote Service/Port${color1}
${tcp_portmon 32768 61000 rhost 0} ${alignr} ${tcp_portmon 32768 61000 rservice 0}
${tcp_portmon 32768 61000 rhost 1} ${alignr} ${tcp_portmon 32768 61000 rservice 1}
${tcp_portmon 32768 61000 rhost 2} ${alignr} ${tcp_portmon 32768 61000 rservice 2}
${tcp_portmon 32768 61000 rhost 3} ${alignr} ${tcp_portmon 32768 61000 rservice 3}
${tcp_portmon 32768 61000 rhost 4} ${alignr} ${tcp_portmon 32768 61000 rservice 4}

${color0}Inbound Connection ${alignr} Local Service/Port${color1}
${tcp_portmon 1 32767 rhost 0} ${alignr} ${tcp_portmon 1 32767 lservice 0}
${tcp_portmon 1 32767 rhost 1} ${alignr} ${tcp_portmon 1 32767 lservice 1}
${tcp_portmon 1 32767 rhost 2} ${alignr} ${tcp_portmon 1 32767 lservice 2}
${tcp_portmon 1 32767 rhost 3} ${alignr} ${tcp_portmon 1 32767 lservice 3}
${tcp_portmon 1 32767 rhost 4} ${alignr} ${tcp_portmon 1 32767 lservice 4}

$hr
${color0}TODO:${color1}
${execi 30 cat /home/username/Desktop/TODO.txt | fold -w40 }
&lt;/pre&gt;
    
&lt;h4&gt;Running Conky at Login&lt;/h4&gt;

&lt;div&gt;

 &lt;div style=&quot;float:right;&quot;&gt;
  &lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXicXaVWGx8wPe3m3hh2zHqoAXP0B1aVywSzf_5b-aMBN-mHsJ7jPfL5jauQN9fFh4iYbePjO2o1kR4VL5yINngETDVqkQ2Du6SxmHgftcJUI07oXb4LeY-wcvsCeQsmCQ_y82MHrIynU/s1600/conkyStartup.png&quot;&gt;&lt;img style=&quot;margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 275px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXicXaVWGx8wPe3m3hh2zHqoAXP0B1aVywSzf_5b-aMBN-mHsJ7jPfL5jauQN9fFh4iYbePjO2o1kR4VL5yINngETDVqkQ2Du6SxmHgftcJUI07oXb4LeY-wcvsCeQsmCQ_y82MHrIynU/s320/conkyStartup.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5500631483612557586&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
 &lt;/div&gt;

 &lt;p&gt;
  In order to enjoy the Conky configuration features described in the section above, you may also want to know how to run Conky automatically when you log in.  To do so, you need to configure a new startup program for your Ubuntu session, which you can do by clicking System -&amp;gt; Preferences -&amp;gt; Sessions.
 &lt;/p&gt;

&lt;/div&gt;

&lt;div style=&quot;clear: both;&quot;&gt;&lt;/div&gt;

&lt;p&gt;
 Sometimes Conky acts finicky if you start it up before your X session has had time to stabilized, so I have my Conky startup program call this shell script.
&lt;/p&gt;
    
&lt;pre class=&quot;brush: bash; tab-size: 2; class-name: code&quot;&gt;
#!/bin/sh
sleep 30 &amp;amp;&amp;amp; conky
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/5141349288272010394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/08/conky.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/5141349288272010394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/5141349288272010394'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/08/conky.html' title='Conky'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkXbZ3vSiuv-F2jhWAFw2p0WPhMeCN3e5NFgnqssNFjfaBnRRMiKznmAYbctiN9dOXJDVC9mbtccuZLvKE0DdsFwOeiNT8_9o4YNxM0jq7Av7ndDwq6IV_z4a5GpQ4vKC4jcPD-zhxEis/s72-c/conkyDesktop.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-3441934561210785371</id><published>2010-08-01T17:33:00.013-05:00</published><updated>2011-01-16T22:46:34.345-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="security"/><category scheme="http://www.blogger.com/atom/ns#" term="Servlet"/><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat"/><title type='text'>Declarative Container Managed Authentication</title><content type='html'>&lt;h4&gt;Motivation&lt;/h4&gt;

&lt;p&gt;
 For web applications that provide dynamic content tailored to individual users, authentication is an important
 concern.  Authentication confirms that a user is, indeed, who they claim to be.  As a result, (web) applications employ
 authentication to confirm the identities of users and protect privileged resources.
&lt;/p&gt;

&lt;p&gt;
 The &lt;a href=&quot;http://jcp.org/en/jsr/detail?id=154&quot;&gt;Java Servlet specification&lt;/a&gt; supports declarative authentication, 
 which eases the implementation of a web application&#39;s authentication strategy.  By using declarative authentication, 
 web developers simply declare &lt;u&gt;that&lt;/u&gt; some or all of the application&#39;s resources are protected.  Web developers are 
 liberated from the burden of writing code that describes &lt;u&gt;how&lt;/u&gt; those security constraints are enforced.
&lt;/p&gt;

&lt;p&gt;
 This tutorial provides a quick overview for web developers who want to take advantage of the Servlet specification&#39;s support of 
 declarative authentication.  The tutorial covers both container-agnostic elements of the web.xml file that support declarative 
 authentication, as well as some authentication-related features of the &lt;a href=&quot;http://tomcat.apache.org/&quot;&gt;Tomcat&lt;/a&gt; servlet 
 container.
&lt;/p&gt;
   
&lt;h4&gt;Securing Web Resources Declaratively&lt;/h4&gt;

&lt;p&gt;

 The web.xml file is the first stop on the way to adding declarative authentication to a web application.  In that file,
 we&#39;ll want to declare what type of authentication should be used.  By appropriately configuring a &amp;lt;login-config&amp;gt; 
 element, we can tell the servlet container what query method should be used when authenticating users.  
 &lt;a href=&quot;http://java.sun.com/javaee/5/docs/tutorial/doc/bncbe.html#bncbn&quot;&gt;Several options&lt;/a&gt; are available, though 
 &lt;a href=&quot;http://java.sun.com/javaee/5/docs/tutorial/doc/bncbe.html#bncbq&quot;&gt;form-based authentication&lt;/a&gt; is the most common. 
&lt;/p&gt;    
    
&lt;pre class=&quot;brush: xml; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;login-config&amp;gt;
  &amp;lt;auth-method&amp;gt;FORM&amp;lt;/auth-method&amp;gt;
  &amp;lt;form-login-config&amp;gt;
    &amp;lt;form-login-page&amp;gt;
      /WEB-INF/pages/login.jsp?info=login
    &amp;lt;/form-login-page&amp;gt;
    &amp;lt;form-error-page&amp;gt;
      /WEB-INF/pages/login.jsp?info=login_failed
    &amp;lt;/form-error-page&amp;gt;
  &amp;lt;/form-login-config&amp;gt;
&amp;lt;/login-config&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
 The &amp;lt;login-config&amp;gt; element above tells the servlet container how it should authenticate users for the related web application.
 Next we need to tell the servlet container which resources in the web application require that the user be authenticated.
&lt;/p&gt;
    
&lt;pre class=&quot;brush: xml; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;security-constraint&amp;gt;
  &amp;lt;web-resource-collection&amp;gt;
    &amp;lt;web-resource-name&amp;gt;Secured Resources&amp;lt;/web-resource-name&amp;gt;
    &amp;lt;description&amp;gt;
      Only logged in users should be able to visit the 
      resources in this collection.
    &amp;lt;/description&amp;gt;
    &amp;lt;url-pattern&amp;gt;/command/*&amp;lt;/url-pattern&amp;gt;
  &amp;lt;/web-resource-collection&amp;gt;
  &amp;lt;auth-constraint&amp;gt;
    &amp;lt;role-name&amp;gt;user&amp;lt;/role-name&amp;gt;
  &amp;lt;/auth-constraint&amp;gt;
  &amp;lt;user-data-constraint&amp;gt;
    &amp;lt;transport-guarantee&amp;gt;NONE&amp;lt;/transport-guarantee&amp;gt;
  &amp;lt;/user-data-constraint&amp;gt;
&amp;lt;/security-constraint&amp;gt;

&amp;lt;security-role&amp;gt;
    &amp;lt;role-name&amp;gt;user&amp;lt;/role-name&amp;gt;
&amp;lt;/security-role&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
 The &amp;lt;security-constraint&amp;gt; element above provides a trivial example in which all URLs that map to the pattern &quot;/command/*&quot; are secured
 so that they may only be accessed by authenticated users in the &quot;user&quot; role. 
&lt;/p&gt;
  
&lt;h4&gt;Defining a JDBCRealm&lt;/h4&gt;

&lt;p&gt;
 All of the authentication-related configuration that we did above in the web.xml file is highly portable since that file will be packaged and 
 deployed with our web application.  Notice, however, that the configuration work we did in web.xml isn&#39;t sufficient by itself to support 
 declarative authentication.  Specifically, we&#39;ve not yet told the Servlet container where and how to access the web application&#39;s list of
 valid users with related passwords.    
&lt;/p&gt;       
&lt;p&gt;

 This is where we have to delve into some container-specific details.  By default, the Tomcat servlet container will attempt to authenticate 
 by reading the user names and passwords defined in its $CATALINA_HOME/conf/tomcat-users.xml file.  Obviously, this is not very convenient 
 if we intend to use a relational database to store information about our web application&#39;s users.
&lt;/p&gt;
&lt;p&gt;
 Thankfully, it&#39;s easy to configure Tomcat to read from a relational database instead of the tomcat-users.xml file when authenticating users.  
 To do so, we&#39;ll need to configure a new &lt;a href=&quot;http://tomcat.apache.org/tomcat-5.5-doc/realm-howto.html#What%20is%20a%20Realm?&quot;&gt;Realm&lt;/a&gt;, 
 which is Tomcat&#39;s generic term for a collection of information about users. 
&lt;/p&gt;
    
&lt;pre class=&quot;brush: xml; tab-size: 2; class-name: code&quot;&gt;
&amp;lt;Realm 
    className=&quot;org.apache.catalina.realm.JDBCRealm&quot;
    driverName=&quot;org.postgresql.Driver&quot;
    connectionURL=&quot;jdbc:postgresql://localhost:5432/YourDatabaseName&quot;
    connectionName=&quot;your_db_username&quot; 
    connectionPassword=&quot;your_db_password&quot;
    userTable=&quot;user_table_name&quot; 
    userNameCol=&quot;user_name_column_name&quot; 
    userCredCol=&quot;user_password_column_name&quot;
    userRoleTable=&quot;uesr_role_table_name&quot; 
    roleNameCol=&quot;role_name_column_name&quot; /&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
 The &amp;lt;Realm&amp;gt; element defined above tells Tomcat how it can use a relational database to authenticate users.    
&lt;/p&gt;

&lt;h4&gt;Configuring Web Application Context&lt;/h4&gt;

&lt;p&gt;
 In the section above we saw how to define a &amp;lt;Realm&amp;gt; element that instructs Tomcat to employ our relational database when 
 authenticating users.  One final consideration remains: where should we place that &amp;lt;Realm&amp;gt; definition?  A single Tomcat server can
 host multiple web applications.  Presumably each of those web applications may want to use a different database to authenticate its users. 
 As a result, we should locate our &amp;lt;Realm&amp;gt; element within the &lt;a href=&quot;http://tomcat.apache.org/tomcat-5.5-doc/config/context.html&quot;&gt;&amp;lt;Context&amp;gt;&lt;/a&gt; 
 element for our web application so that the Realm applies only to our web application. 
&lt;/p&gt;
       
&lt;p&gt;
 A good way to include a &amp;lt;Realm&amp;gt; element within the web application&#39;s &amp;lt;Context&amp;gt; is to include a 
 &lt;a href=&quot;http://wiki.metawerx.net/wiki/Context.xml&quot;&gt;META-INF/context.xml&lt;/a&gt; file in our web application.  By defining a &amp;lt;Realm&amp;gt; element 
 within such a file, we can ensure that the application will use the appropriate relational database for authentication, regardless of which 
 Tomcat server it is deployed to.
&lt;/p&gt;

&lt;h4&gt;Granting Security Privileges&lt;/h4&gt;

&lt;p&gt;
 One final, useful note is that  we may need to augment the &lt;a href=&quot;http://tomcat.apache.org/tomcat-5.5-doc/security-manager-howto.html&quot;&gt;security constraints&lt;/a&gt; 
 for our application server if we want it to use an external relational database for user authentication.  For the Tomcat Servlet container, we can add an entry 
 to the $CATALINA_HOME/config/catalina.policy file.
&lt;/p&gt;       
    
&lt;pre class=&quot;brush: text; tab-size: 2; class-name: code&quot;&gt;
grant {
    permission java.net.SocketPermission &quot;localhost:5432&quot;, 
    &quot;connect,resolve&quot;;
};    
&lt;/pre&gt;

&lt;p&gt;
 The above statement grants permission for any class in the servlet container to lookup and connect to our database, which runs on the localhost at port 5432.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/3441934561210785371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/08/container-managed-authentication.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/3441934561210785371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/3441934561210785371'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/08/container-managed-authentication.html' title='Declarative Container Managed Authentication'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-144505856620411498.post-1432365268766359275</id><published>2010-08-01T14:08:00.036-05:00</published><updated>2011-01-16T22:44:09.436-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><category scheme="http://www.blogger.com/atom/ns#" term="RegularExpression"/><title type='text'>Beware a slow death by regular expressions!</title><content type='html'>&lt;h4&gt;Overview &amp;amp; Motivation&lt;/h4&gt;

&lt;p&gt;The Java programming language provides &lt;a href=&quot;http://java.sun.com/docs/books/tutorial/essential/regex/&quot;&gt;great support for regular expressions&lt;/a&gt;. In general, the performance of regular expressions in Java is very good. The trade-off for that excellent performance is a (somewhat) protracted API. To see what I mean, have a a look at a canonical regular expression example from Sun&#39;s javadoc:&lt;/p&gt;

&lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;
Pattern p = Pattern.compile(&quot;a*b&quot;);
Matcher m = p.matcher(&quot;aaaaab&quot;);
boolean b = m.matches();
&lt;/pre&gt;

&lt;p&gt;Kind of verbose, considering all we&#39;ve accomplished is checking a single &lt;a href=&quot;http://download-llnw.oracle.com/javase/6/docs/api/java/lang/CharSequence.html&quot;&gt;CharacterSequence&lt;/a&gt; for a match against one regular expression! Such complaints about decreased simplicity are likely what motivated Sun to provide some regular expression &quot;convenience&quot; methods inside the API for the String class.  Specifically, as of version 6, the &lt;a href=&quot;http://java.sun.com/javase/6/docs/api/java/lang/String.html&quot;&gt;String API&lt;/a&gt; provides five such convenience methods:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;public boolean &lt;a href=&quot;http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#matches%28java.lang.String%29&quot;&gt;matches&lt;/a&gt;(String regex);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;public String &lt;a href=&quot;http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#replaceFirst%28java.lang.String,%20java.lang.String%29&quot;&gt;replaceFirst&lt;/a&gt;(String regex, String replacement);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;public String &lt;a href=&quot;http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29&quot;&gt;replaceAll&lt;/a&gt;(String regex, String replacement);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;public String[] &lt;a href=&quot;http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#split%28java.lang.String%29&quot;&gt;split&lt;/a&gt;(String regex);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;public String[] &lt;a href=&quot;http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#split%28java.lang.String,%20int%29&quot;&gt;split&lt;/a&gt;(String regex, int limit);&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Each of the above convenience methods constructs and delegates the method call to &lt;a href=&quot;http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html&quot;&gt;Pattern&lt;/a&gt; and &lt;a href=&quot;http://java.sun.com/javase/6/docs/api/java/util/regex/Matcher.html&quot;&gt;Matcher&lt;/a&gt; objects. What&#39;s not immediately obvious from the documentation for those convenience methods is that they become extremely inefficient as you execute them many thousands of times.&lt;/p&gt;

&lt;h4&gt;Reg. Exp. API Timing Data&lt;/h4&gt;

&lt;p&gt;
Consider the following bit of code that illuminates the inefficiency of the &lt;code&gt;String.matches(regex)&lt;/code&gt; method:
&lt;/p&gt;

&lt;pre class=&quot;brush: java; tab-size: 2; class-name: code&quot;&gt;
public class RegExpExerciser
{
 public static void main(String[] args)
 {

  int numTimes = 10000000;

  String regexp = &quot;a*b&quot;;
  String toMatch = &quot;aaaaab&quot;;

  long begin1 = System.currentTimeMillis();
  for (int i = 0; i &amp;lt; numTimes; i++)
  {
   toMatch.matches(regexp);
  }
  System.out.println(
   &quot;Milliseconds using convenience method from String: &quot; 
   + (System.currentTimeMillis() - begin1)
  );

  long begin2 = System.currentTimeMillis();
  Pattern p = Pattern.compile(regexp);
  for (int i = 0; i &amp;lt; numTimes; i++)
  {
   p.matcher(toMatch).matches();
  }
  System.out.println(
   &quot;Milliseconds when re-using compiled reg. exp. pattern: &quot; 
   + (System.currentTimeMillis() - begin2)
  );

 }
}
&lt;/pre&gt;

&lt;p&gt;Executing the above code, my box reveals these times:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;Milliseconds using convenience method from String: 5074
Milliseconds when re-using compiled reg. exp. pattern: 1720&lt;/pre&gt;&lt;/blockquote&gt;

&lt;h4&gt;RegExpHelper.java to the Rescue!&lt;/h4&gt;

&lt;p&gt;
The code sample above clearly demonstrates that the time to compile a regular expression &lt;a href=&quot;http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html&quot;&gt;Pattern&lt;/a&gt; dominates the time required to actually check whether a given string matches the pattern. Utilizing that key insight, I offer a helper class in the &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommon/index.html&quot;&gt;Big-Oh Software Common library&lt;/a&gt; that provides simple APIs for working with regular expressions without sacrificing performance: &lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommon/xref/net/big_oh/common/utils/RegExpHelper.html&quot;&gt;RegExpHelper.java&lt;/a&gt; (&lt;a href=&quot;http://big-oh.googlecode.com/svn/site/1.BigOhSoftwareFrameworksAndTools/BigOhSoftwareCommon/apidocs/net/big_oh/common/utils/RegExpHelper.html&quot;&gt;javadoc&lt;/a&gt;).  The key feature to note about that class is that it caches compiled regular expressions, making its methods both simple and efficient.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://computergoboom.blogspot.com/feeds/1432365268766359275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://computergoboom.blogspot.com/2010/08/beware-slow-death-by-regular.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/1432365268766359275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/144505856620411498/posts/default/1432365268766359275'/><link rel='alternate' type='text/html' href='http://computergoboom.blogspot.com/2010/08/beware-slow-death-by-regular.html' title='Beware a slow death by regular expressions!'/><author><name>Dave Wingate</name><uri>http://www.blogger.com/profile/18059486973779580311</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEgkcBxkaciatSFO3QJx29WBVxtnG1L8g-wC1vcLqmvewisEhiWAHLu1xXPXEFgWplDyFsOs7CSqA1jJMBH0Z2yE7rEVi9_PhsesJI3IDkR9HH23lOE3c2dFZDvuoLy0A/s220/Tofino_082.JPG'/></author><thr:total>0</thr:total></entry></feed>