http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java
----------------------------------------------------------------------
diff --git 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java
 
b/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java
deleted file mode 100644
index b2125f6..0000000
--- 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.oodt.profile.handlers.lightweight;
-
-import java.util.List;
-import org.apache.oodt.profile.RangedProfileElement;
-
-/**
- * Searchable profile element with a range of valid values.
- *
- * @author Kelly
- * @version $Revision: 1.1.1.1 $
- */
-public class SearchableRangedProfileElement extends RangedProfileElement 
implements SearchableProfileElement {
-       public SearchableRangedProfileElement(SearchableProfile profile, String 
name, String id, String desc, String type,
-               String unit, List synonyms, boolean obligation, int 
maxOccurrence, String comment, String min, String max) {
-               super(profile, name, id, desc, type, unit, synonyms, 
obligation, maxOccurrence, comment, min, max);
-       }
-
-       public Result result(String value, String operator) {
-               Result rc = FalseResult.INSTANCE;
-               double numeric = Double.parseDouble(value);
-               if (operator.equals("EQ") || operator.equals("LIKE")) {
-                       if (Double.parseDouble(min) <= numeric && numeric <= 
Double.parseDouble(max)) {
-                         rc = new MatchingResult(this);
-                       }
-               } else if (operator.equals("NE") || operator.equals("NOTLIKE")) 
{
-                       if (numeric < Double.parseDouble(min) || numeric > 
Double.parseDouble(max)) {
-                         rc = new MatchingResult(this);
-                       }
-               } else if (operator.equals("LT")) {
-                       if (numeric > Double.parseDouble(min)) {
-                         rc = new MatchingResult(this);
-                       }
-               } else if (operator.equals("GT")) {
-                       if (numeric < Double.parseDouble(max)) {
-                         rc = new MatchingResult(this);
-                       }
-               } else if (operator.equals("LE")) {
-                       if (numeric >= Double.parseDouble(min)) {
-                         rc = new MatchingResult(this);
-                       }
-               } else {
-                       if (numeric <= Double.parseDouble(max)) {
-                         rc = new MatchingResult(this);
-                       }
-               }
-               return rc;
-       }
-}

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java
----------------------------------------------------------------------
diff --git 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java
 
b/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java
deleted file mode 100644
index 77786e1..0000000
--- 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.oodt.profile.handlers.lightweight;
-
-import java.util.HashSet;
-import java.util.List;
-import org.apache.oodt.profile.ResourceAttributes;
-import org.w3c.dom.Element;
-
-/**
- * Resource attributes that can be searched.
- *
- * @author Kelly
- * @version $Revision: 1.1.1.1 $
- */
-public class SearchableResourceAttributes extends ResourceAttributes {
-       public SearchableResourceAttributes(SearchableProfile profile, Element 
node) {
-               super(profile, node);
-       }
-
-       /**
-        * Produce a search result.
-        *
-        * @param value Desired value.
-        * @param operator What operator to use for comparison.
-        * @return a <code>Result</code> value.
-        */
-       public Result result(String name, String value, String operator) {
-               if ("Identifier".equals(name)) {
-                 return computeResult(identifier, value, operator);
-               } else if ("Title".equals(name)) {
-                 return computeResult(title, value, operator);
-               } else if ("Format".equals(name)) {
-                 return computeResult(formats, value, operator);
-               } else if ("Description".equals(name)) {
-                 return computeResult(description, value, operator);
-               } else if ("Creator".equals(name)) {
-                 return computeResult(creators, value, operator);
-               } else if ("Subject".equals(name)) {
-                 return computeResult(subjects, value, operator);
-               } else if ("Publisher".equals(name)) {
-                 return computeResult(publishers, value, operator);
-               } else if ("Contributor".equals(name)) {
-                 return computeResult(contributors, value, operator);
-               } else if ("Date".equals(name)) {
-                 return computeResult(dates, value, operator);
-               } else if ("Type".equals(name)) {
-                 return computeResult(types, value, operator);
-               } else if ("Source".equals(name)) {
-                 return computeResult(sources, value, operator);
-               } else if ("Language".equals(name)) {
-                 return computeResult(languages, value, operator);
-               } else if ("Relation".equals(name)) {
-                 return computeResult(relations, value, operator);
-               } else if ("Coverage".equals(name)) {
-                 return computeResult(coverages, value, operator);
-               } else if ("Rights".equals(name)) {
-                 return computeResult(rights, value, operator);
-               } else if ("resContext".equals(name)) {
-                 return computeResult(contexts, value, operator);
-               } else if ("resClass".equals(name)) {
-                 return computeResult(clazz, value, operator);
-               } else if ("resLocation".equals(name)) {
-                 return computeResult(locations, value, operator);
-               } else {
-                 throw new IllegalArgumentException("Unknown attribute \"" + 
name + "\"");
-               }
-       }
-
-       private Result computeResult(String a, String b, String op) {
-               int c = a.compareTo(b);
-               boolean t;
-               if ("EQ".equals(op) || "LIKE".equals(op)) {
-                 t = c == 0;
-               } else if ("GE".equals(op)) {
-                 t = c >= 0;
-               } else if ("GT".equals(op)) {
-                 t = c > 0;
-               } else if ("LE".equals(op)) {
-                 t = c <= 0;
-               } else if ("LT".equals(op)) {
-                 t = c < 0;
-               } else if ("NE".equals(op) || "NOTLIKE".equals(op)) {
-                 t = c != 0;
-               } else {
-                 throw new IllegalArgumentException("Unknown relational 
operator \"" + op + "\"");
-               }
-               if (t) {
-                 return new MatchingResult(new 
HashSet(profile.getProfileElements().values()));
-               } else {
-                 return FalseResult.INSTANCE;
-               }
-       }
-
-       private Result computeResult(List a, String b, String op) {             
-               if (a == null || a.isEmpty()) {
-                 return FalseResult.INSTANCE;
-               }
-
-               Result f = FalseResult.INSTANCE;
-               Result t = new MatchingResult(new 
HashSet(profile.getProfileElements().values()));
-               Result rc = f;
-               if ("EQ".equals(op) || "LIKE".equals(op)) {
-                 if (a.contains(b)) {
-                       rc = t;
-                 } else if ("NE".equals(op) || "NOTLIKE".equals(op)) {
-                       if (!a.contains(b)) {
-                         rc = t;
-                       } else if ("LT".equals(op) || "GT".equals(op) || 
"LE".equals(op) || "GE".equals(op)) {
-                         for (Object anA : a) {
-                               String value = (String) anA;
-                               rc = computeResult(value, b, op);
-                               if (rc != f) {
-                                 break;
-                               }
-                         }
-                       } else {
-                         throw new IllegalArgumentException("Unknown 
relational operator \"" + op + "\"");
-                       }
-                 }
-               }
-               return rc;
-       }
-
-
-}

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java
----------------------------------------------------------------------
diff --git 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java
 
b/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java
deleted file mode 100644
index f480877..0000000
--- 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.oodt.profile.handlers.lightweight;
-
-import java.util.List;
-import org.apache.oodt.profile.UnspecifiedProfileElement;
-
-/**
- * Searchable profile element with unspecified values.
- *
- * @author Kelly
- * @version $Revision: 1.1.1.1 $
- */
-public class SearchableUnspecifiedProfileElement extends 
UnspecifiedProfileElement implements SearchableProfileElement {
-       public SearchableUnspecifiedProfileElement(SearchableProfile profile, 
String name, String id, String desc, String type,
-               String unit, List synonyms, boolean obligation, int 
maxOccurrence, String comment) {
-               super(profile, name, id, desc, type, unit, synonyms, 
obligation, maxOccurrence, comment);
-       }
-
-       public Result result(String value, String operator) {
-               return new MatchingResult(this);
-       }
-}

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java
----------------------------------------------------------------------
diff --git 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java 
b/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java
deleted file mode 100644
index 003670a..0000000
--- 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.oodt.profile.handlers.lightweight;
-
-import java.util.Set;
-import org.apache.oodt.profile.ProfileElement;
-
-/**
- * A union of matching elements.
- *
- * @author Kelly
- */
-class Union implements Result {
-       /**
-        * Construct a union.
-        *
-        * @param lhs Left-hand side
-        * @param rhs Right-hand side.
-        */
-       public Union(Result lhs, Result rhs) {
-               this.lhs = lhs;
-               this.rhs = rhs;
-       }
-
-       public Set matchingElements() {
-               Set union = ProfileElement.profiles(lhs.matchingElements());
-               union.addAll(ProfileElement.profiles(rhs.matchingElements()));
-               Set rc = ProfileElement.elements(union, lhs.matchingElements());
-               rc.addAll(ProfileElement.elements(union, 
rhs.matchingElements()));
-               return rc;
-       }
-
-       public String toString() {
-               return "union[" + lhs + "," + rhs + "]";
-       }
-
-       /** Left-hand side of the result. */
-       private Result lhs;
-
-       /** Right-hand side of the result. */
-       private Result rhs;
-}

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java
----------------------------------------------------------------------
diff --git 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java
 
b/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java
deleted file mode 100644
index cf488a6..0000000
--- 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.oodt.profile.handlers.lightweight;
-
-import java.util.Map;
-
-/**
- * A where-expression.
- *
- * @author Kelly
- */
-interface WhereExpression {
-       /**
-        * Compute the result tree of this where expression based on the map of 
profile elements.
-        *
-        * @param resAttr Resource attributes to check.
-        * @param elements Map from {@link String} element name to {@link 
ProfileElement}.
-        * @return A result tree that when evaluated yields matching {@link 
ProfileElement}s.
-        */
-       Result result(SearchableResourceAttributes resAttr, Map elements);
-
-       /**
-        * Return a simplified version of this expression.
-        *
-        * Our result generation can't handle "NOT" expressions (like "not 
(blah < 3)")
-        * since we can't do set inversion, so we simplify the expression by 
removing all
-        * "NOT" nodes.
-        *
-        * @return An equivalent expression without negative nodes.
-        */
-       WhereExpression simplify();
-
-       /**
-        * Negate this expression.
-        *
-        * @return The negation of this expression.
-        */
-       WhereExpression negate();
-}

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html
----------------------------------------------------------------------
diff --git 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html
 
b/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html
deleted file mode 100644
index 56d73cd..0000000
--- 
a/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-  <head>
-    <title>Lightweight Profile Handler.
-    </title>
-  </head>
-  <body>
-    <p>Lightweight profile handler.  The lightweight profile handler
-      is lightweight because it doesn't rely on any external
-      search/retrieval mechanism.  It's 100% pure Java, baby.
-    </p>
-    <p>To use this handler, create an XML file that contains the
-      profiles you want to serve.  Set the system property
-      <code>profiles.url</code>
-      to the location of that file.  Fire 'er up.
-    </p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/examples/src.jar
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/examples/src.jar 
b/profile/src/site/resources/examples/src.jar
deleted file mode 100644
index 3edbb96..0000000
Binary files a/profile/src/site/resources/examples/src.jar and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/class.png
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/class.png 
b/profile/src/site/resources/images/class.png
deleted file mode 100644
index d8a7ab4..0000000
Binary files a/profile/src/site/resources/images/class.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/class.psd
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/class.psd 
b/profile/src/site/resources/images/class.psd
deleted file mode 100644
index 3a20fd4..0000000
Binary files a/profile/src/site/resources/images/class.psd and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/delegation.png
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/delegation.png 
b/profile/src/site/resources/images/delegation.png
deleted file mode 100644
index fd8d5cf..0000000
Binary files a/profile/src/site/resources/images/delegation.png and /dev/null 
differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/delegation.psd
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/delegation.psd 
b/profile/src/site/resources/images/delegation.psd
deleted file mode 100644
index 02a2fd9..0000000
Binary files a/profile/src/site/resources/images/delegation.psd and /dev/null 
differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/grid-profile.jpg
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/grid-profile.jpg 
b/profile/src/site/resources/images/grid-profile.jpg
deleted file mode 100644
index de71567..0000000
Binary files a/profile/src/site/resources/images/grid-profile.jpg and /dev/null 
differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/stack.png
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/stack.png 
b/profile/src/site/resources/images/stack.png
deleted file mode 100644
index 10856a5..0000000
Binary files a/profile/src/site/resources/images/stack.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/stack.psd
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/stack.psd 
b/profile/src/site/resources/images/stack.psd
deleted file mode 100644
index 6d23e2d..0000000
Binary files a/profile/src/site/resources/images/stack.psd and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/tree.png
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/tree.png 
b/profile/src/site/resources/images/tree.png
deleted file mode 100644
index 52cf31f..0000000
Binary files a/profile/src/site/resources/images/tree.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/resources/images/tree.psd
----------------------------------------------------------------------
diff --git a/profile/src/site/resources/images/tree.psd 
b/profile/src/site/resources/images/tree.psd
deleted file mode 100644
index b51ce99..0000000
Binary files a/profile/src/site/resources/images/tree.psd and /dev/null differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/site.xml
----------------------------------------------------------------------
diff --git a/profile/src/site/site.xml b/profile/src/site/site.xml
deleted file mode 100644
index 3cfecdf..0000000
--- a/profile/src/site/site.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more contributor
-license agreements.  See the NOTICE.txt file distributed with this work for
-additional information regarding copyright ownership.  The ASF licenses this
-file to you under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License.  You may obtain a copy of
-the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<project name="Profile Service">
-
-  <body>
-    <links>
-      <item name="OODT" href="../oodt-site/"/>
-      <item name="Grid" href="../grid/"/>
-    </links>
-
-    <menu ref="reports" inherit="bottom"/>
-    <menu name="User's Guide">
-      <item name="Information Captured" href="info/"/>
-      <item name="Querying Profiles" href="querying/"/>
-      <item name="Profile Repr." href="rep/"/>
-      <item name="Basic Handler" href="handler/"/>
-      <item name="Advanced Handler" href="adv/"/>
-    </menu>
-    
-  </body>
-</project>

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/xdoc/adv/index.xml
----------------------------------------------------------------------
diff --git a/profile/src/site/xdoc/adv/index.xml 
b/profile/src/site/xdoc/adv/index.xml
deleted file mode 100755
index 3c8b913..0000000
--- a/profile/src/site/xdoc/adv/index.xml
+++ /dev/null
@@ -1,1072 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more contributor
-license agreements.  See the NOTICE.txt file distributed with this work for
-additional information regarding copyright ownership.  The ASF licenses this
-file to you under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License.  You may obtain a copy of
-the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<document>
-  <properties>
-    <title>Developing a Real Profile Handler</title>
-    <author email="[email protected]">Sean Kelly</author>
-  </properties>
-  <!-- Wizzy Noise - Haiku -->
-  <body>
-    <section name="Developing a Real Profile Handler">
-      <p>In the <a href="../handler/">basic profile handler
-         tutorial</a>, we developed a profile handler that answered
-       every query with a list of exactly zero profile objects.  It
-       also responded to requests to retrieve a profile by a
-       specific ID with <code>null</code>, meaning "not found by
-       this handler."  Useful, huh?  Not really.
-      </p>
-
-      <p>But it did get our profile server ready for <em>this</em>
-       tutorial, where we'll write a <em>real</em> profile handler
-       that analyzes incoming queries, consults a local "database",
-       constructs a set of matching profile results, and responds to
-       requests to profiles by ID.  Get some fresh coffee, because
-       this is going to be a tough one.
-      </p>
-
-      <p>And yes, you'll need to have gone through <em>all</em> of the
-       following before proceeding:
-      </p>
-
-      <ul>
-       <li><a href="../info/">Information Captured in a Profile</a></li>
-       <li><a href="../querying/">Querying Profiles</a></li>
-       <li><a href="../rep">Profile Representation</a></li>
-       <li><a href="../handler">Developing a Profile Handler</a></li>
-      </ul>
-    </section>
-
-    <section name="The Music Database">
-      <p>Let's say you've got an OODT <a href="/grid-product/">product
-         server</a> already running that serves up your favorite
-         music files.  All you have to do is pass in the URI to a
-         track and it spits back the MP3 data which can run into your
-         favorite media player.  You've set it up so your URIs are
-         all unique for each track, and you just have to pass in an
-         unparsed XMLQuery like <code>urn:sk:tr5B7E.mp3</code> and
-         you get the matching data.
-      </p>
-
-      <p>But since you're not in the habit of memorizing hexadecimal
-       numbers inside of URIs, let's write a profile server who's job
-       it is to take queries for specific artists, genres, albums,
-       ratings, track titles, and so forth, and spit out the matching
-       profiles.  The profiles have a places for a URI (in the
-       <code>Identifier</code> field) that you can then pass to the
-       hypothetical product server to get the track data.  (In fact,
-       this is a common OODT pattern: profile query to do resource
-       location, product query to do resource retrieval.)  While
-       you're listening to the track, you can read all sorts of other
-       juicy metadata about it by examining the returned profile.
-      </p>
-
-      <subsection name="The Metadata">
-       <p>For this demonstration, we'll just focus on three kinds of
-         metadata instead of going all-out, <a
-           href="http://www.apple.com/itunes/";>iTunes</a> style:
-       </p>
-
-       <ul>
-         <li>Artist name</li>
-         <li>Album name</li>
-         <li>Track name</li>
-       </ul>
-
-       <p>Each profile will describe a single track.  The resource
-         attributes will have:
-       </p>
-
-       <ul>
-         <li>The URI of the track as the <code>Identifier</code>.</li>
-         <li>The name of the track as the <code>Title</code>.</li>
-         <li>The name of the artist as the <code>Creator</code>.</li>
-       </ul>
-
-       <p>In addition, we'll put in two profile elements:</p>
-
-       <ul>
-         <li>The name of the album as an
-           <code>EnumeratedProfileElement</code>.
-         </li>
-         <li>The name of the artist as an
-           <code>EnumeratedProfileElement</code>.  Yes, this is
-           redundant with the artist named as the <code>Creator</code>
-           in the resource attributes; but one profile element by
-           itself would get too lonely!</li>
-       </ul>
-      </subsection>
-
-      <subsection name="Query Style">
-       <p>Both product handlers and profile handlers get to choose
-         whether they want unparsed query expressions in their
-         XMLQuery objects or if they want parsed query expressions.
-         Parsed query expressions generate the "where" boolean stack.
-         While the product server that this profile server is meant
-         to work with wants unparsed ones, we'll use parsed
-         expressions for this profile handler.  Why?  Well, having a
-         well-defined query language and a way to operate on it will
-         save a little trouble from us having to generate a parser.
-       </p>
-
-       <p>The queries will use element names <code>artist</code>,
-         <code>album</code>, and <code>track</code> only, to match
-         what we'll save in our music database.  Here are a couple example 
queries:
-       </p>
-
-       <source>artist = Beatles AND album = Revolver
-track = 'Blue Suede Shoes'</source>
-      </subsection>
-    </section>
-
-    <section name="Developing the Handler">
-      <p>We'll develop the handler in parts, so we can discuss each
-       section, and then show the entire source file.
-      </p>
-
-      <subsection name='Making the "Database"'>
-       <p>Our music database will be nothing more than Java objects
-         kept in memory.  We'll create separate objects of three
-         classes:
-       </p>
-
-       <ul>
-         <li><code>Artist</code>.  <code>Artist</code> objects represent
-             people or groups who create music.  <code>Artist</code>s
-             will have zero or more <code>Track</code>s.
-         </li>
-         <li><code>Album</code>.  <code>Album</code> objects are
-           collections of <code>Track</code>s.
-         </li>
-         <li><code>Track</code>.  <code>Track</code> objects appear
-           on one <code>Album</code> and are made by one
-           <code>Artist</code>.  They have the URN necessary to pass
-           to the hypothetical music product server in order to
-           actually play music.
-         </li>
-       </ul>
-
-       <p>A better music model would probably separate out artists
-         and composers, account for remixes, compilation albums,
-         re-issues, multiple renditions, and so forth, but this is
-         government work, and it'll do.
-       </p>
-
-       <p>Here's class <code>Artist</code>:</p>
-
-       <source>class Artist {
-  public Artist(String name) {
-    this.name = name;
-    tracks = new ArrayList();
-  }
-  public String getName() {
-    return name;
-  }
-  public List getTracks() {
-    return tracks;
-  }
-  public int hashCode() {
-    return name.hashCode();
-  }
-  public boolean equals(Object obj) {
-    if (obj == this) return true;
-    if (!(obj instanceof Artist)) return false;
-    Artist rhs = (Artist) obj;
-    return name.equals(rhs.name);
-  }
-  private String name;
-  private List tracks;
-}</source>
-
-       <p>As you can see, <code>Artist</code>s have a name and a
-         <code>List</code> of <code>Track</code>s they've made.  Now,
-         here's class <code>Album</code>:
-       </p>
-
-       <source>class Album {
-  public Album(String name) {
-    this.name = name;
-    tracks = new ArrayList();
-  }
-  public String getName() {
-    return name;
-  }
-  public List getTracks() {
-    return tracks;
-  }
-  public int hashCode() {
-    return name.hashCode();
-  }
-  public boolean equals(Object obj) {
-    if (obj == this) return true;
-    if (!(obj instanceof Album)) return false;
-    Album rhs = (Album) obj;
-    return name.equals(rhs.name);
-  }
-  private String name;
-  private List tracks;
-}</source>
-
-       <p>As with <code>Artist</code>s, <code>Album</code>s (or
-         should that be <em>Alba</em>?) have names and collections of
-         <code>Track</code>s.  Finally, here's class <code>Track</code>:
-       </p>
-
-       <source>class Track {
-  public Track(String name, URI id, Artist artist,
-    Album album) {
-    this.name = name;
-    this.id = id;
-    this.artist = artist;
-    this.album = album;
-    artist.getTracks().add(this);
-    album.getTracks().add(this);
-  }
-  public String getName() { return name; }
-  public URI getID() { return id; }
-  public Artist getArtist() { return artist; }
-  public Album getAlbum() { return album; }
-  public int hashCode() {
-    return name.hashCode() ^ id.hashCode();
-  }
-  public boolean equals(Object obj) {
-    if (obj == this) return true;
-    if (!(obj instanceof Track)) return false;
-    Track rhs = (Track) obj;
-    return id.equals(rhs.id);
-  }
-  private String name;
-  private URI id;
-  private Artist artist;
-  private Album album;
-}</source>
-
-       <p>As you can see from the code, a track belongs to an
-         <code>Artist</code> and to an <code>Album</code> and has a
-         URI which you can use to get to the track's MP3 data.
-         Finally, with these three "entity" classes in hand, we can
-         create a music database:
-       </p>
-
-       <source>class DB {
-  public static Set ARTISTS = new HashSet();
-  public static Set ALBUMS = new HashSet();
-  public static Set TRACKS = new HashSet();
-  static {
-    Artist bach = new Artist("Bach");
-    Album brandenburg123
-      = new Album("Brandenburg Concerti 1, 2, 3");
-    Album brandenburg456
-      = new Album("Brandenburg Concerti 4, 5, 6");
-    Track brandenburg1
-      = new Track("Brandenburg Concerto #1",
-      URI.create("urn:sk:tr91BC.mp3"), bach,
-      brandenburg123);
-    Track brandenburg2
-      = new Track("Brandenburg Concerto #2",
-      URI.create("urn:sk:tr311E.mp3"), bach,
-      brandenburg123);
-    Track brandenburg3
-      = new Track("Brandenburg Concerto #3",
-      URI.create("urn:sk:trA981.mp3"), bach,
-      brandenburg123);
-    Track brandenburg4
-      = new Track("Brandenburg Concerto #4",
-      URI.create("urn:sk:tr233A.mp3"), bach,
-      brandenburg456);
-    Track brandenburg5
-      = new Track("Brandenburg Concerto #5",
-      URI.create("urn:sk:trA6E5.mp3"), bach,
-      brandenburg456);
-
-     Track brandenburg6
-      = new Track("Brandenburg Concerto #6",
-      URI.create("urn:sk:tr01E9.mp3"), bach,
-      brandenburg456);
-
-    Artist delerium = new Artist("Delerium");
-    Album semantic = new Album("Semantic Spaces");
-    Album poem = new Album("Poem");
-    Track flowers
-      = new Track("Flowers Become Screens",
-      URI.create("urn:sk:tr3A5E.mp3"), delerium,
-      semantic);
-    Track metaphor = new Track("Metaphor",
-      URI.create("urn:sk:tr0E13.mp3"), delerium,
-      semantic);
-    Track innocente = new Track("Innocente",
-      URI.create("urn:sk:tr004A.mp3"), delerium,
-      poem);
-    Track aria = new Track("Aria",
-      URI.create("urn:sk:tr004A.mp3"), delerium,
-      poem);
-
-    ARTISTS.add(bach);
-    ARTISTS.add(delerium);
-    ALBUMS.add(brandenburg123);
-    ALBUMS.add(brandenburg456);
-    ALBUMS.add(semantic);
-    ALBUMS.add(poem);
-    TRACKS.add(brandenburg1);
-    TRACKS.add(brandenburg2);
-    TRACKS.add(brandenburg3);
-    TRACKS.add(brandenburg4);
-    TRACKS.add(brandenburg5);
-    TRACKS.add(brandenburg6);
-    TRACKS.add(flowers);
-    TRACKS.add(metaphor);
-    TRACKS.add(innocente);
-    TRACKS.add(aria);
-  }
-}</source>
-
-       <p>(Please don't judge this limited collection as the breadth
-         of my listening tastes.  It's actually much narrower now!)
-         In this small database, we've got two artists, Bach and
-         Delerium, with four albums: <i>Brandenburg Concerti 1, 2,
-         3</i> and <i>4, 5, 6</i>; and <i>Semantic Spaces</i> and
-         <i>Poem</i>.  And we've got 10 tracks: 3 belonging to one
-         album, 3 belonging to another, 2 belonging to yet another,
-         and the last 2 belonging to the last album.  Six are by
-         Bach, and four by Delerium.  Each track has
-       </p>
-      </subsection>
-
-      <subsection name="Querying our Database">
-       <p>Recall that the <a href="/edm-query/">XMLQuery</a>'s query
-         language uses triples of the form (element, relation,
-         literal) like <code>album != Poem</code>.  The relations
-         include =, !=, &lt;, &gt;, &lt;=, &gt;=, LIKE, and NOTLIKE.
-         The triples are linked with AND, OR, and NOT.  For this
-         tutorial, we'll do the = and != cases.  The rest you can
-         fill in for your own edification.  Our approach will be to
-         examine the postfix "where" boolean stack and convert it
-         into an infix boolean expression tree.  We'll ask the tree
-         to evaluate itself into a matching set of
-         <code>Track</code>s.  Then all we have to do is descibe the
-         matching <code>Track</code>s as <code>Profile</code>
-         objects.
-       </p>
-
-       <p>Let's start by defining a node in our expression tree:</p>
-
-       <source>interface Expr {
-  Set evaluate();
-}</source>
-
-       <p>The <code>evaluate</code> method means "evaluate into a
-         <code>Set</code> of matching <code>Track</code> objects."
-         With this interface, we can then define classes that make up
-         different flavors of tree nodes.  One of the easier ones is
-         a constant tree node that either matches <em>every</em>
-         track available (constant true) or <em>none</em> of them
-         (constant false):
-       </p>
-
-       <source>class Constant implements Expr {
-  public Constant(boolean value) {
-    this.value = value;
-  }
-  public Set evaluate() {
-    return value? DB.TRACKS
-      : Collections.EMPTY_SET;
-  }
-  private boolean value;
-}</source>
-
-       <p>Next, let's do negation.  This takes the set complement of
-         an existing tree node:
-       </p>
-
-       <source>class Not implements Expr {
-  public Not(Expr expr) {
-    this.expr = expr;
-  }
-  public Set evaluate() {
-    Set matches = expr.evaluate();
-    Set inverse = new HashSet();
-    for (Iterator i = DB.TRACKS.iterator();
-      i.hasNext();) {
-      Track t = (Track) i.next();
-      if (!matches.contains(t))
-        inverse.add(t);
-    }
-    return inverse;
-  }
-  private Expr expr;
-}</source>
-
-       <p>As you can see, this node is constructed with another tree
-         node expression.  To evaluate this node, we evaluate the
-         expression passed in.  Then we take its inverse by iterating
-         through each track in the database and adding it to the
-         matching set if it <em>doesn't</em> occur in the
-         expression's matching set.
-       </p>
-
-       <p>The union tree node takes two expressions and adds the two
-         sets of matching tracks together:
-       </p>
-
-       <source>class Or implements Expr {
-  public Or(Expr lhs, Expr rhs) {
-    this.lhs = lhs;
-    this.rhs = rhs;
-  }
-  public Set evaluate() {
-    Set left = lhs.evaluate();
-    Set right = rhs.evaluate();
-    left.addAll(right);
-    return left;
-  }
-  private Expr lhs;
-  private Expr rhs;
-}</source>
-
-       <p>The intersection tree node evaluates to <code>Track</code>s
-         that occur only in both expressions' tracks:
-       </p>
-
-       <source>class And implements Expr {
-  public And(Expr lhs, Expr rhs) {
-    this.lhs = lhs;
-    this.rhs = rhs;
-  }
-  public Set evaluate() {
-    Set left = lhs.evaluate();
-    Set right = rhs.evaluate();
-    left.retainAll(right);
-    return left;
-  }
-  private Expr lhs;
-  private Expr rhs;
-}</source>
-
-       <p>With these nodes, we can cover the logical operators AND,
-         OR, and NOT that appear in a postfix "where" stack, as well
-         as an empty "where" stack, which, by convention, is meant to
-         be a constant "true", matching all available resources.  Now
-         we just have to handle triples (element, relation, literal).
-         First up, comparisons against <code>Artist</code>s:
-       </p>
-
-       <source>class ArtistExpr implements Expr {
-  public ArtistExpr(String op, String value) {
-    this.op = op;
-    this.value = value;
-  }
-  public Set evaluate() {
-    Set tracks = new HashSet();
-    if ("EQ".equals(op)) {
-      for (Iterator i = DB.ARTISTS.iterator();
-        i.hasNext();) {
-        Artist a = (Artist) i.next();
-        if (a.getName().equals(value))
-          tracks.addAll(a.getTracks());
-      }
-    } else if ("NE".equals(op)) {
-      for (Iterator i = DB.ARTISTS.iterator();
-        i.hasNext();) {
-        Artist a = (Artist) i.next();
-        if (!a.getName().equals(value))
-          tracks.addAll(a.getTracks());
-      }
-    } else throw new
-      UnsupportedOperationException("NYI");
-    return tracks;
-  }
-  private String op;
-  private String value;
-}</source>
-
-       <p>For an expression like <code>artist = Bach</code> or
-         <code>artist != Delerium</code> we use a expression node
-         object of the above class.  When it's <code>EQ</code>, we
-         iterate through all the artists in the database and, when
-         the artist's name matches, add all of that artist's tracks
-         to the set of matches.  When it's <code>NE</code>, we
-         instead add all of the artists' tracks whose name
-         <em>doesn't</em> match.  (The other relational operators,
-         <code>LT</code>, <code>GT</code>, <code>LE</code>,
-         <code>GE</code>, <code>LIKE</code>, and <code>NOTLIKE</code>
-         currently throw an exception.  You're welcome to try to
-         implement those.)
-       </p>
-
-       <p>The <code>AlbumExpr</code> expression node is quite similar:</p>
-
-       <source>class AlbumExpr implements Expr {
-  public AlbumExpr(String op, String value) {
-    this.op = op;
-    this.value = value;
-  }
-  public Set evaluate() {
-    Set tracks = new HashSet();
-    if ("EQ".equals(op)) {
-      for (Iterator i = DB.ALBUMS.iterator();
-        i.hasNext();) {
-        Album a = (Album) i.next();
-        if (a.getName().equals(value))
-          tracks.addAll(a.getTracks());
-      }
-    } else if ("NE".equals(op)) {
-      for (Iterator i = DB.ALBUMS.iterator();
-        i.hasNext();) {
-        Album a = (Album) i.next();
-        if (!a.getName().equals(value))
-          tracks.addAll(a.getTracks());
-      }
-    } else throw new
-      UnsupportedOperationException("NYI");
-    return tracks;
-  }
-  private String op;
-  private String value;
-}</source>
-
-       <p>(Another exercise for the reader: refactor out common code
-         between these two classes.)  Finally, the
-         <code>TrackExpr</code> node is for expressions like
-         <code>track = Poem</code>:
-       </p>
-
-       <source>class TrackExpr implements Expr {
-  public TrackExpr(String op, String value) {
-    this.op = op;
-    this.value = value;
-  }
-  public Set evaluate() {
-    Set tracks = new HashSet();
-    if ("EQ".equals(op)) {
-      for (Iterator i = DB.TRACKS.iterator();
-        i.hasNext();) {
-        Track t = (Track) i.next();
-        if (t.getName().equals(value))
-          tracks.add(t);
-      }
-    } else if ("NE".equals(op)) {
-      for (Iterator i = DB.TRACKS.iterator();
-        i.hasNext();) {
-        Track t = (Track) i.next();
-        if (!t.getName().equals(value))
-          tracks.add(t);
-      }
-    } else throw new
-      UnsupportedOperationException("NYI");
-    return tracks;
-  }
-  private String op;
-  private String value;
-}</source>
-
-       <p>For <code>EQ</code>, we just iterate through every track in
-         the database and add it to the set of matching tracks if the
-         names match the name passed into the user's query.  For
-         <code>NE</code>, we add them if their names <em>don't</em> match.
-       </p>
-
-       <p>That completes all the code for the expression tree.  Now
-         we can start working on the class that implements the
-         <code>ProfileHandler</code> interface,
-         <code>MusicHandler</code>.  Here, we'll build that
-         expression tree with the incoming <code>XMLQuery</code>,
-         which provides its "where" element stack as a postfix
-         boolean expression.  Here's the approach:
-       </p>
-
-       <ol>
-         <li>Make a new, empty stack.</li>
-         <li>For each element in the "where" stack:
-           <ol>
-             <li>If it's an element name (<code>artist</code>,
-               <code>album</code>, <code>track</code>), push the name
-               onto the stack.
-             </li>
-             <li>If it's a literal value (<code>Bach</code>,
-               <code>Poem</code>, etc.), push it onto the stack.
-             </li>
-             <li>If it's a relational operator (<code>EQ</code>, 
<code>NE</code>, etc.):
-               <ol>
-                 <li>Pop two values off.</li>
-                 <li>Push an <code>ArtistExpr</code>, <code>AlbumExpr</code>, 
or <code>TrackExpr</code>.</li>
-               </ol>
-             </li>
-             <li>It it's a logical operator:
-               <ul>
-                 <li>For <code>AND</code>, pop two values off and push an 
<code>And</code> node.</li>
-                 <li>For <code>OR</code>, pop two values off and push an 
<code>Or</code> node.</li>
-                 <li>For <code>NOT</code>, pop one value off and push a 
<code>Not</code> node.</li>
-               </ul>
-             </li>
-           </ol>
-         </li>
-       </ol>
-       <p>In the end, there will be one element left on the stack, an
-         <code>Expr</code> node representing the root of the
-         expression tree.  Here's the method of
-         <code>MusicHandler</code> that implements the algorithm:
-       </p>
-
-       <source>private static Expr transform(XMLQuery q) {
-  Stack stack = new Stack();
-  for (Iterator i = q.getWhereElementSet()
-    .iterator(); i.hasNext();) {
-    QueryElement e = (QueryElement) i.next();
-    String keyword = e.getValue();
-    String type = e.getRole();
-    if ("elemName".equals(type))
-       stack.push(keyword);
-    else if ("LITERAL".equals(type))
-       stack.push(keyword);
-    else if ("RELOP".equals(type))
-       addRelational(keyword, (String)stack.pop(),
-         (String)stack.pop(), stack);
-    else if ("LOGOP".equals(type))
-       addLogical(keyword, stack);
-    else throw new
-       IllegalArgumentException("Unknown query "
-         + type + " type");
-  }
-  if (stack.size() == 0)
-    return new Constant(true);
-  else if (stack.size() > 1)
-    throw new IllegalArgumentException("Unbalanced"
-      + " query");
-  else return (Expr) stack.pop();
-}</source>
-
-       <p>For relational and logical operators, this method defers to
-         two other utility methods, which we'll see shortly.  After
-         iterating through the entire "where" set, we check to see if
-         there's an empty stack.  That's the case where the user
-         passes in an empty expression, which by convention we'll
-         take to mean they want everything.  Otherwise, there should
-         be just one <code>Expr</code> node on the stack, the root of
-         the expression tree.
-       </p>
-
-       <p>To handle adding a <code>RELOP</code>, we pop two values
-         off, the element name (<code>artist</code>,
-         <code>album</code>, or <code>track</code>), and the literal
-         value the user wants (<code>Bach</code>, <code>Poem</code>,
-         etc.), along with the operator and the stack:
-       </p>
-
-       <source>private static void addRelational(String op,
-  String value, String kind, Stack stack) {
-  if ("artist".equals(kind))
-    stack.push(new ArtistExpr(op, value));
-  else if ("album".equals(kind))
-    stack.push(new AlbumExpr(op, value));
-  else if ("track".equals(kind))
-    stack.push(new TrackExpr(op, value));
-  else throw new
-    IllegalArgumentException("Unknown profile"
-      + " element " + kind);
-}</source>
-
-       <p>This method then replaces the popped off values with the
-         matching <code>Expr</code> class for artists, albums, or
-         tracks.
-       </p>
-
-       <p>To handle adding a <code>LOGOP</code>, we pass the logical
-         operator and the entire stack to this method:
-       </p>
-
-       <source>private static void addLogical(String op,
-  Stack stack) {
-  if ("AND".equals(op))
-    stack.push(new And((Expr)stack.pop(),
-      (Expr) stack.pop()));
-  else if ("OR".equals(op))
-    stack.push(new Or((Expr)stack.pop(),
-      (Expr) stack.pop()));
-  else if ("NOT".equals(op))
-    stack.push(new Not((Expr)stack.pop()));
-  else throw new
-    IllegalArgumentException("Illegal operator "
-      + op);
-}</source>
-
-       <p>With all this code in place we can generate the expression
-         tree.  Let's look at an example.  Suppose when constructing the
-         <code>XMLQuery</code>, the user passed in</p>
-
-       <source>artist = Bach and not album = Poem or track != Aria</source>
-
-       <p>The XMLQuery query language generates a postfix stack of
-         <code>QueryElement</code> objects in the "where" list:
-       </p>
-
-       <img src="../images/stack.png" alt="Stack" />
-
-       <p>And we then create this tree:</p>
-
-       <img src="../images/tree.png" alt="Tree" />
-
-       <p>Calling the root's <code>evaluate</code> method then yields
-         a <code>java.util.Set</code> of <code>Track</code> objects
-         that match that expression.
-       </p>
-
-       <p>OK, we've got a set of <code>Track</code>s.  But what we
-         want are a set of <em><code>Profile</code>s</em>.  The next
-         step is to describe those tracks using the profile metadata
-         model.
-       </p>
-      </subsection>
-
-      <subsection name="Describing Tracks">
-       <p>Query handlers serve up <code>List</code>s of
-         <code>Profile</code> objects, where <code>Profile</code>s
-         contain metadata descriptions of resources.  For this
-         tutorial, the resources we're describing are music tracks,
-         represented by instances of <code>Track</code> objects.
-         When the handler's <code>findProfiles</code> and
-         <code>get</code> methods are called by the OODT framework to
-         service a request, all we have to do is find the matching
-         <code>Track</code> (or <code>Track</code>s) and create
-         matching <code>Profile</code>s.
-       </p>
-
-       <p>Recall that we're setting up the resource attributes of the
-         profile so that
-       </p>
-       <ul>
-         <li>The URI of the track appears in the <code>Identifier</code>.</li>
-         <li>The name of the track appears in the <code>Title</code>.</li>
-         <li>The name of the artist appears the <code>Creator</code>.</li>
-       </ul>
-
-       <p>In addition, we'll put in two profile elements:</p>
-
-       <ul>
-         <li>The name of the album as an
-           <code>EnumeratedProfileElement</code>.
-         </li>
-         <li>The name of the artist redundantly as an
-           <code>EnumeratedProfileElement</code>.
-         </li>
-       </ul>
-
-       <p>Now, let's create a utility method <code>describe</code>
-         which takes a <code>java.util.Set</code> of matching
-         <code>Track</code>s and yields a <code>java.util.List</code>
-         of corresponding <code>Profile</code>s:
-       </p>
-
-       <source>private static List describe(Set tracks) {
-  List profiles = new ArrayList();
-  for (Iterator i = tracks.iterator();
-    i.hasNext();) {
-    Track t = (Track) i.next();
-    String id = t.getID().toString();
-    String trackName = t.getName();
-    String albumName = t.getAlbum().getName();
-    String artistName = t.getArtist().getName();
-    Profile p = createProfile(id, trackName,
-      albumName, artistName);
-    profiles.add(p);
-  }
-  return profiles;
-}</source>
-
-       <p>We build a list of <code>Profile</code>s by calling another
-         method, <code>createProfile</code>.  It takes the track's
-         URI, its name, the name of the album on which it appears,
-         and the name of the artist who created it, and yields a
-         <code>Profile</code>:
-       </p>
-
-       <source>private static Profile createProfile(String id,
-  String trackName, String albumName,
-  String artistName) {
-  Profile p = new Profile();
-  ProfileAttributes pa=new ProfileAttributes(id,
-    "1.0", "profile", "active", "unclassified",
-    /*parent*/null, /*children*/EL,
-    "1.3.6.1.4.1.7655", /*revNotes*/EL);
-  p.setProfileAttributes(pa);
-  ResourceAttributes ra=new ResourceAttributes(p,
-    id, trackName,
-    Collections.singletonList("audio/mpeg"),
-    /*desc*/null,
-    Collections.singletonList(artistName),
-    /*subjects*/EL, /*pubs*/EL, /*contrib*/EL,
-    /*dates*/EL, /*types*/EL, /*sources*/EL,
-    /*langs*/EL, /*relations*/EL, /*covs*/EL,
-    /*rights*/EL,
-    Collections.singletonList("SK.Music"),
-    "granule", "system.productServer",
-    Collections.singletonList("urn:eda:rmi:"
-      + "MyProductServer"));
-    p.setResourceAttributes(ra);
-    EnumeratedProfileElement artistElem =
-    new EnumeratedProfileElement(p, "artist",
-    "artist", "Name of the artist of a work",
-    "string", "name", /*syns*/EL, /*ob*/true,
-    /*maxOccur*/1, /*comment*/null,
-    Collections.singletonList(artistName));
-  p.getProfileElements().put("artist",
-    artistElem);
-  EnumeratedProfileElement albumElem =
-    new EnumeratedProfileElement(p, "album",
-    "album", "Name of album where track occurs",
-    "string", "name", /*syns*/EL, /*ob*/true,
-    /*maxOccur*/1, /*comment*/null,
-    Collections.singletonList(albumName));
-  p.getProfileElements().put("album",
-    albumElem);
-  return p;
-}</source>
-
-       <p>The profile attributes say that</p>
-       <ul>
-         <li>The ID of the profile itself is the same as the track's URI.</li>
-         <li>The version of the profile is 1.0.</li>
-         <li>The type is "profile".</li>
-         <li>It's currently active.</li>
-         <li>It's not top-secret, it's "unclassified".</li>
-         <li>It has no parent profile.</li>
-         <li>It has no child profiles.</li>
-         <li>The registration authority has OID 1.3.6.1.4.1.7655</li>
-         <li>There are no revision notes.</li>
-       </ul>
-
-       <p>The resource attributes say that</p>
-       <ul>
-         <li>The Identifier is the track's URI.</li> <li>The Title is
-         the track's title.</li> <li>The sole Format in which the
-         track is available is <code>audio/mpeg</code>.</li>
-         <li>There's no description.</li> <li>The sole Creator is the
-         name of the artist.</li> <li>There are no subject keywords,
-         publishers, contributors, dates, types, sources, languages,
-         relations, coverages, nor rights.</li>
-         <li>The sole resource context is "Tutorial.Music".</li>
-         <li>The resource's aggregation is "granule", meaning this profile is 
describing a single, discrete resource.</li>
-         <li>The resource's class is "system.productServer", meaning you need 
to contact a product server at the resource location to retrieve the 
resource.</li>
-         <li>The resource location is 
<code>urn:eda:rmi:MyProductServer</code>.</li>
-       </ul>
-
-       <p>Finally, the two profile elements tell (again) who the
-         artist was and also on what album the track appears.
-       </p>
-
-       <p>What's with all the <code>EL</code>s?  It's just to save on 
typing:</p>
-
-       <source>private static final List EL
-  = Collections.EMPTY_LIST;</source>
-      </subsection>
-
-      <subsection name="Implementng the Interface">
-       <p>The <code>ProfileHandler</code> interface stipulates two
-         methods, one for finding profiles given an
-         <code>XMLQuery</code> and another for retrieving a single
-         profile given its ID.  With all of these utility methods in
-         place, these are both easy to write.  First, the
-         <code>findProfiles</code> method:
-       </p>
-
-       <source>public List findProfiles(XMLQuery q) {
-  Expr expr = transform(q);
-  Set matches = expr.evaluate();
-  List profiles = describe(matches);
-  return profiles;
-}</source>
-
-       <p>The algorithm should be painfully obvious by now: transform
-         the query to a tree, evaluate the tree into a set of
-         matching tracks, and describe the tracks.
-       </p>
-
-       <p>The <code>get</code> method takes a profile's ID and
-         returns the matching profile, or <code>null</code> if it's
-         not found.  Since we're using the track's ID as the
-         profile's ID as well, we can just iterate through our
-         tracks, find the one with the matching ID, and
-         <code>describe</code> it:
-       </p>
-
-       <source>public Profile get(String id) {
-  URI uri = URI.create(id);
-  for (Iterator i = DB.TRACKS.iterator();
-    i.hasNext();) {
-    Track t = (Track) i.next();
-    if (t.getID().equals(uri))
-      return createProfile(t.getID().toString(),
-        t.getName(), t.getAlbum().getName(),
-        t.getArtist().getName());
-  }
-  return null;
-}</source>
-
-      </subsection>
-
-      <subsection name="Complete Source Code">
-       <p>Don't feel like cutting and pasting all of those code
-         fragments?  No problem.  All of the source files are
-         available <a href="../examples/src.jar">in a jar</a>.
-       </p>
-      </subsection>
-    </section>
-
-    <section name="Compiling the Handler">
-      <p>As with the <a
-         href="../handler/"><code>NullHandler</code></a>, we'll use the
-       J2SDK command-line tools.  And if you've gone through the <a
-         href="../handler/"><code>NullHandler</code> tutorial</a>, you've
-       got all the dependent jars in place already.  Just put the
-       <code>MusicHandler.java</code> and all the related source files
-       under <code>$PS_HOME/src</code>, compile, and build the jar:
-      </p>
-
-      <source>% <b>ls src</b>
-Album.java         Expr.java
-AlbumExpr.java     MusicHandler.java
-And.java           Not.java
-Artist.java        NullHandler.java
-ArtistExpr.java    Or.java
-Constant.java      Track.java
-DB.java            TrackExpr.java
-% <b>javac -extdirs lib -d classes src/*.java</b>
-% <b>ls classes</b>
-Album.class         Expr.class
-AlbumExpr.class     MusicHandler.class
-And.class           Not.class
-Artist.class        NullHandler.class
-ArtistExpr.class    Or.class
-Constant.class      Track.class
-DB.class            TrackExpr.class
-% <b>cd classes</b>
-% <b>jar -uf ../lib/my-handler.jar *.class</b>
-% <b>cd ..</b>
-% <b>jar -tf lib/my-handler.jar</b>
-META-INF/
-META-INF/MANIFEST.MF
-NullHandler.class
-Album.class
-AlbumExpr.class
-And.class
-Artist.class
-ArtistExpr.class
-Constant.class
-DB.class
-Expr.class
-MusicHandler.class
-Not.class
-Or.class
-Track.class
-TrackExpr.class</source>
-
-      <p>We also need to update the <code>$PS_HOME/bin/ps</code>
-       script.  Currently, it's instantiating just the
-       <code>NullHandler</code>; we need it to instantiate the
-       <code>MusicHandler</code> too.  Stop any currently running
-       profile server by pressing CTRL+C (or whatever your interrupt
-       key is) in the window running the server.  Then edit the
-       script so it reads as follows:
-      </p>
-
-      <source>#!/bin/sh
-exec java -Djava.ext.dirs=$PS_HOME/lib \
-    -Dhandlers=NullHandler,MusicHandler \
-    jpl.eda.ExecServer \
-    jpl.eda.profile.rmi.ProfileServiceImpl \
-    urn:eda:rmi:MyProfileService</source>
-
-      <p>Now the profile server will delegate to <em>two</em>
-       handlers: the <code>NullHandler</code> and the
-       <code>MusicHandler</code>.  With more than one handler, the
-       OODT framework calls each one in turn and collects all of the
-       matching profiles together to return to the
-       <code>ProfileClient</code>.  (Of course, the
-       <code>NullHandler</code> never actually generates any matching
-       profiles.)
-      </p>
-    </section>
-
-    <section name="Querying the Profile Server">
-      <p>Start the profile server by running
-       <code>$PS_HOME/bin/ps</code> in one window (presumably the RMI
-       registry is still running in another window).  In yet another
-       window, we'll run our <code>$PS_HOME/bin/pc</code> script to
-       query the profile server:
-      </p>
-
-      <source>% <b>$PS_HOME/bin/pc 'artist = Delerium
- AND album != Poem OR artist = Bach'</b><![CDATA[
-Object context ready; delegating to:
-[jpl.eda.object.jndi.RMIContext@dec8b3]
-[<?xml version="1.0" encoding="UTF-8"?>
-<profile><profAttributes><profId>urn:sk:tr91BC.mp3</profId>...]]></source>
-
-      <p>Whoa!  There's a huge load of XML!  In fact what the
-       <code>ProfileClient</code> is printing is a
-       <code>java.util.List</code> of profiles in XML format, each
-       separated by a comma, and the whole list in square brackets.
-       If you search this output carefully, though, you can pick out
-       the <code>&lt;Title&gt;</code> elements and see indeed that
-       we've got six matching tracks:
-      </p>
-
-      <ul>
-       <li>Brandenburg Concerto #1</li>
-       <li>Brandenburg Concerto #2</li>
-       <li>Brandenburg Concerto #3</li>
-       <li>Brandenburg Concerto #4</li>
-       <li>Brandenburg Concerto #5</li>
-       <li>Brandenburg Concerto #6</li>
-       <li>Flowers Become Screens</li>
-       <li>Metaphor</li>
-      </ul>
-
-      <p>Sure enough, this matches the XMLQuery query language
-       expression we passed in: There are tracks by Delerium but
-       <em>not</em> from the Poem album, and there are all the tracks
-       by Bach.
-      </p>
-    </section>
-
-    <section name='Conclusion'>
-      <p>In this long tutorial we developed a real profile handler
-       that answered queries by transforming them from postfix stacks
-       into expression trees and using those trees to query an
-       in-memory database made of Java objects.  We then described
-       matching data by creating <code>Profile</code>s.
-      </p>
-
-      <p>You might be thinking that this seems like a lot of work, and
-       there might be some easier ways to go.  You could use the
-       <code>LightweightProfileHandler</code> for resources that
-       never change, but only if you don't have too many of them and
-       don't mind managing potentially large XML documents.  You
-       could choose to use unparsed XMLQuery expressions and instead
-       make the user query in the same language as your data system,
-       obviating the need for complex expression trees.
-      </p>
-
-      <p>However, with the tools presented in this tutorial, you could
-       adapt the expression tree code to generating system-specific
-       queries, and describe those results with as much or as little
-       detail as necessary.
-      </p>
-
-      <p>Happy profiling!</p>
-    </section>
-  </body>
-</document>

http://git-wip-us.apache.org/repos/asf/oodt/blob/098cc4fa/profile/src/site/xdoc/handler/index.xml
----------------------------------------------------------------------
diff --git a/profile/src/site/xdoc/handler/index.xml 
b/profile/src/site/xdoc/handler/index.xml
deleted file mode 100755
index ba02b14..0000000
--- a/profile/src/site/xdoc/handler/index.xml
+++ /dev/null
@@ -1,595 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more contributor
-license agreements.  See the NOTICE.txt file distributed with this work for
-additional information regarding copyright ownership.  The ASF licenses this
-file to you under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License.  You may obtain a copy of
-the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<document>
-  <properties>
-    <title>Developing a Profile Handler</title>
-    <author email="[email protected]">Sean Kelly</author>
-  </properties>
-  <!-- Shift - Nexus Overload -->
-  <body>
-    <section name="Developing a Profile Handler">
-      <p>Profiles describe resources. But where do profiles come from?
-       From profile handlers. Profile handlers are interchangeable
-       components of a profile server that accept queries for
-       profiles and return matching profiles. Profile handlers take a
-       static or a dynamic collection of information and serve an
-       equivalent set of profiles. Developing a new profile handler
-       is as simple as writing a Java class that implements a
-       specific interface or two.
-      </p>
-
-      <p>If you're not already familiar with the <code>XMLQuery</code>
-       class, go ahead and <a href="/edm-query/tutorial/">take its
-         tutorial now</a>.  We'll wait!
-      </p>
-    </section>
-
-    <section name="Introduction">
-      <p>Profile handlers handle queries for profiles.  They're the
-       interchangeable part of a profile server that you can develop
-       for special needs.  Profile servers delegate all incoming
-       requests to zero or more profile handlers, as shown in the
-       following class diagram:
-      </p>
-
-      <img src="../images/delegation.png" alt="Delegation model" />
-
-      <p>Developing, testing, and deploying a new profile handler
-       involves:
-      </p>
-      <ol>
-       <li>Creating a class that implements (however indirectly)
-         the <code>jpl.eda.profile.handlers.ProfileHandler</code> interface.
-       </li>
-       <li>Creating a new process that runs either the RMI or
-           CORBA <code>ProfileServiceImpl</code> class,
-           specifying the name of your handler class.
-       </li>
-       <li>Starting the server and sending in queries.
-       </li>
-      </ol>
-      <p>This document describes each of these steps in detail.</p>
-    </section>
-
-    <section name="Writing the Handler Class">
-      <p>Writing the class that handles profile queries and delivers
-       profile results is easily the hardest part in developing a new
-       kind of profile server.  Profile servers' handlers can serve
-       profiles describing static resources, can synthesize profile
-       on the fly to describe resources, and can create profile
-       metadata for resources that change all the time.
-      </p>
-      
-      <p>Understanding the resources you're trying to describe with
-       profiles is the most important thing you can do before
-       beginning to write your profile handler:
-      </p>
-
-      <ul>
-       <li>Do you always have the same set of static resources?
-         If so, you can write a static profile document to describe
-         them and use the
-         <code>LightweightProfileHandler</code>, thus
-         avoiding having to write a new handler at all.
-       </li>
-       <li>Do you have resources that never change, but may add to or
-         remove from that set?  If so, you can use the
-         <code>OracleProfileImpl</code> handler which uses an Oracle
-         database to store a set of profiles that you can update.
-       </li>
-       <li>Do you have resources that do change, or that come
-         from a dynamic set of data?  If so, you'll have to write a
-         handler.
-       </li>
-      </ul>
-
-      <subsection name="Choosing the Handler Interface to Implement">
-       <p>The OODT Framework provides two handler interfaces (one is
-         an extension of the other):
-       </p>
-       <ul>
-         <li><code>jpl.eda.profile.handlers.ProfileHandler</code>
-             is the basic profile handler.  It defines methods for
-           <em>handling</em> searches for profiles.
-         </li>
-
-         <li><code>jpl.eda.profile.handlers.ProfileManager</code> is an
-           extension that not just <em>handles</em> profile queries
-           but also <em>manages</em> the set of profiles maintained
-           by the server, by providing methods for adding to,
-           removing from, and updating the set of managed profiles.
-         </li>
-       </ul>
-      
-       <p>For nearly all applications, the <code>ProfileHandler</code>
-         interface is sufficient.  If you need to provide profile
-         management capabilities, it still may be handy to start with
-         the <code>ProfileHandler</code> interface, implement and test
-         its methods, and <em>then</em> change to the
-         <code>ProfileManager</code>.
-       </p>
-      </subsection>
-
-      <subsection name="The ProfileHandler Interface">
-       <p>The <code>ProfileHandler</code> interface is
-         as follows:
-       </p>
-
-       <source>package jpl.eda.profile.handlers;
-
-import java.util.List;
-import jpl.eda.profile.Profile;
-import jpl.eda.profile.ProfileException;
-import jpl.eda.xmlquery.XMLQuery;
-
-public interface ProfileHandler {
-  List findProfiles(XMLQuery query) throws ProfileException;
-  Profile get(String profID) throws ProfileException;
-}</source>
-
-       <p>The two methods are described in detail below.</p>
-
-       <dl>
-         <dt><code>findProfiles</code></dt>
-         <dd>This method accepts a query in the form of an
-           <code>XMLQuery</code> object and returns a
-           Java <code>List</code> of
-           <code>Profile</code> objects that match.  If
-           there are no matches, this method must return an empty
-           list.  If an error occurs, it should throw the
-             <code>ProfileException</code>.
-
-           <p>This is by far the most used and most important
-             method, and really is the <i>raison
-             d'etre</i> for profile servers.  It's
-             what the OODT Framework uses to allow clients to ask
-             your server for resources based on metadata .
-           </p>
-         </dd>
-         <dt><code>get</code></dt>
-         <dd>This method accepts the ID of a profile in the form
-           of a Java <code>String</code> and returns
-           either a <code>Profile</code> object with that
-           ID or null if the ID is unknown.  This method enables a
-           client to retrieve a profile using a priori knowledge of
-           the profile's ID (perhaps from a previous search).
-         </dd>
-       </dl>
-      </subsection>
-
-      <subsection name="The ProfileManager Interface">
-       <p>The <code>ProfileManager</code> interface
-         builds on the <code>ProfileHandler</code>, and is
-         listed below:
-       </p>
-       <source>package jpl.eda.profile.handlers;
-
-import java.util.Collection;
-import java.util.Iterator;
-import jpl.eda.profile.Profile;
-import jpl.eda.profile.ProfileException;
-import jpl.eda.xmlquery.XMLQuery;
-
-public interface ProfileManager extends ProfileHandler {
-  void add(Profile profile) throws ProfileException;
-  void addAll(Collection collection) throws ProfileException;
-  void clear() throws ProfileException;
-  boolean contains(Profile profile) throws ProfileException;
-  boolean containsAll(Collection collection) throws ProfileException;
-  Collection getAll() throws ProfileException;
-  boolean isEmpty() throws ProfileException;
-  Iterator iterator() throws ProfileException;
-  boolean remove(String profID, String version) throws ProfileException;
-  boolean remove(String profID) throws ProfileException;
-  int size() throws ProfileException;
-  void replace(Profile profile) throws ProfileException;
-}</source>
-
-       <p>If you choose to implement a profile manager, please see
-         the API documentation for the
-         <code>ProfileManager</code> class for the
-         expectations of each method.
-       </p>
-      </subsection>
-    </section>
-
-    <section name="Our First Profile Handler">
-      <p>Although not terribly useful, a &#8220;null&#8221; profile
-       handler is a good example to start with because it is small and
-       will make sure your environment is in good working order before
-       proceeding to a real profile handler.
-      </p>
-      
-      <p>What's a &#8220;null&#8221; profile handler?  It's one that
-       serves no profiles.  That is, for any query with
-       <code>findProfiles</code> and any retrieval with
-       <code>get</code> it never returns any profiles.
-      </p>
-
-      <subsection name="Directory Layout">
-       <p>For these examples, we'll work on a kind of Unix system
-         with a <code>csh</code> shell.  Other shell users or Windows
-         users will need to adjust.  We'll also use the J2SDK
-         command-line tools.  If you're using an Integrated
-         Development Environment of some sort, please adjust
-         accordingly.
-       </p>
-
-       <p>We'll create a "home" directory for our profile servers
-         with subdirectories to hold specific components like source
-         code, jar files, and scripts.  We'll call this home
-         directory by an environment variable, <code>PS_HOME</code>
-         (PS for Profile Server), so that scripts won't have to refer
-         to things by relative paths:
-       </p>
-
-       <source>% <b>mkdir ps</b>
-% <b>cd ps</b>
-% <b>setenv PS_HOME `pwd`</b>
-% <b>mkdir bin classes lib src</b></source>
-      </subsection>
-
-      <subsection name="Source File">
-       <p>One of the easier parts is the source itself for the
-         &#8216;null&#8217; profile handler.  Here it is:
-       </p>
-       <source>import java.util.Collections;
-import java.util.List;
-import jpl.eda.profile.Profile;
-import jpl.eda.profile.handlers.ProfileHandler;
-import jpl.eda.xmlquery.XMLQuery;
-
-public class NullHandler implements ProfileHandler {
-  public List findProfiles(XMLQuery query) {
-    return Collections.EMPTY_LIST;
-  }
-  public Profile get(String id) {
-    return null;
-  }
-}</source>
-
-       <p>Note that for every query, the
-         <code>findProfiles</code> method returns an empty list
-         (meaning that no profiles matched), and that for any retrieval
-         the <code>get</code> method returns null, meaning that
-         the handler believes there's no such profile.
-       </p>
-       <p>This class should be compiled into a file named
-         <code>$PS_HOME/src/NullHandler.java</code>
-         since it is a public class.
-       </p>
-
-       <p><em>Note:</em> Profile handler classes <em>must</em> be
-         public <em>and</em> provide a no-arguments
-         constructor.  You should retrieve any initialization
-         settings through the System Properties or by other means
-         specific to your profile handler.
-       </p>
-      </subsection>
-      
-      <subsection name="Compiling the Handler">
-       <p>Compiling this profile handler requires the following
-         dependent components:
-       </p>
-
-       <ul>
-         <li><a href="/grid-profile/">Profile Service</a>.  This
-           defines the entire profile model, handler interfaces,
-           servers, clients, and so forth.
-         </li>
-         <li><a href="/edm-query/">Query Expression</a>.  This
-           defines the <code>XMLQuery</code> and related classes.
-         </li>
-       </ul>
-
-       <p>Download the binary distributions of the above two packages
-         and copy the jar file from each into the
-         <code>$PS_HOME/lib</code> directory.  Then you can compile
-         the <code>NullHandler.java</code> file.
-       </p>
-
-       <source>% <b>ls</b>
-bin   classes   lib    src
-% <b>ls -l lib</b>
-total 244
--rw-r--r--  1 kelly  kelly   43879 28 Feb 07:05 edm-query-2.0.2.jar
--rw-r--r--  1 kelly  kelly  201453 28 Feb 07:01 grid-profile-3.0.2.jar
-% <b>javac -extdirs lib -d classes src/NullHandler.java</b>
-% <b>ls -l classes</b>
-total 4
--rw-r--r--  1 kelly  kelly  511 28 Feb 07:07 NullHandler.class
-% <b>jar -cf lib/my-handler.jar -C classes NullHandler.class</b>
-% <b>jar -tf lib/my-handler.jar</b>
-META-INF/
-META-INF/MANIFEST.MF
-NullHandler.class</source>
-
-       <p>We now have a new jar file, <code>my-handler.jar</code>
-         which contains our &#8216;null&#8217; profile handler,
-         compiled and ready to go.
-       </p>
-      </subsection>
-
-      <subsection name="Starting an RMI Registry">
-       <p>Clients access profile servers with an open-ended set of
-         network protocols.  We currently have implementations for
-         RMI and CORBA.  For this tutorial, we'll use RMI, since it's
-         enormously less complex.  Clients of RMI systems first
-         contact an RMI registry and look up a server object's
-         network address.  The registry maintains mappings from a
-         server object's name to its network address.  When servers
-         start up, they register with the RMI registry so clients can
-         later find them.
-       </p>
-
-       <p>To start an RMI Registry, you'll need the following components:</p>
-
-       <ul>
-         <li><a href="/edm-commons/">EDM Common Components</a>.
-           These are common utilities used by every OODT
-           service.
-         </li>
-         <li><a href="/rmi-registry/">OODT RMI Registry</a>.  This is the
-           actual RMI registry.</li>
-       </ul>
-
-       <p>Download each component's binary distribution, unpack each
-         one, and take collect the jar files into the
-         <code>lib</code> directory.  The RMI Registry will also need
-         the <code>grid-profile</code> jar file, which we've already
-         got.
-       </p>
-
-       <source>% <b>ls -l $PS_HOME/lib</b>
-total 404
--rw-r--r--  1 kelly  kelly  149503 28 Feb 07:28 edm-commons-2.2.5.jar
--rw-r--r--  1 kelly  kelly   43879 28 Feb 07:05 edm-query-2.0.2.jar
--rw-r--r--  1 kelly  kelly  201453 28 Feb 07:01 grid-profile-3.0.2.jar
--rw-r--r--  1 kelly  kelly     796 28 Feb 07:07 my-handler.jar
--rw-r--r--  1 kelly  kelly    8055 28 Feb 07:28 rmi-registry-1.0.0.jar</source>
-
-       <p>Now all we need is a convenient script to start the RMI
-         registry.  We'll call it <code>rmi-reg</code> and stick it
-         in the <code>bin</code> directory.  Here's the
-         <code>rmi-reg</code> script:</p>
-
-       <source>#!/bin/sh
-exec java -Djava.ext.dirs=$PS_HOME/lib \
-    gov.nasa.jpl.oodt.rmi.RMIRegistry</source>
-
-       <p>This script tells the Java virtual machine to find
-         extension jars in the directory <code>$PS_HOME/lib</code>.  It
-         then says that the main class to execute is
-         <code>gov.nasa.jpl.oodt.rmi.RMIRegistry</code>.
-       </p>
-
-       <p>Go ahead and make this script executable and start the RMI
-         Registry. In another window (with the appropriate setting of
-         <code>PS_HOME</code>), run
-         <code>$PS_HOME/bin/rmi-reg</code>.  You should see output
-         similar to the following:
-       </p>
-
-       <source>% <b>chmod 755 $PS_HOME/bin/rmi-reg</b>
-% <b>$PS_HOME/bin/rmi-reg</b>
-Mon Feb 28 07:30:13 CST 2005: no objects registered</source>
-
-       <p>The RMI Registry is now running.  Every two minutes it will
-         display an update of all registered objects.  Naturally, we
-         don't have any profile service running right now, so it will
-         say <code>no objects registered</code>.  Go ahead and ignore
-         this window for now.  It's time to start our profile server.
-       </p>
-      </subsection>
-
-      <subsection name="Starting the Profile Server">
-       <p>With our handler compiled and our RMI registry running,
-         we're ready to start our profile server.  As said before,
-         profile servers delegate to zero or more profile handlers to
-         actually handle all incoming requests.  You tell the profile
-         server what handlers to instantiate by naming their classes
-         in a system property.  That property is called
-         <code>handlers</code>, and its value is a comma-separated
-         list of fully qualified class names, including the package
-         name prefixes.  Since our <code>NullHandler</code> is just
-         in the default package, <code>NullHandler</code> <em>is</em>
-         its fully-qualified class name.
-       </p>
-
-       <p>Profile server processes require the following components
-         in addition to the ones we've downloaded so far:</p>
-
-       <ul>
-         <li><a href="http://ws.apache.org/xmlrpc";>Apache
-             XML-RPC</a>.  This is used internally by OODT services.
-           Download version 1.1, not a later version!  If you prefer,
-           you can <a
-             href="http://ibiblio.org/maven/xmlrpc/jars/xmlrpc-1.1.jar";>fetch
-             the jar file directly</a>.
-         </li>
-
-         <li><a href="http://jena.sourceforge.net/";>Jena Semantic Web
-             Framework for Java</a>.  This is used by the classes
-             that represent profiles.  You'll need version 1.6.1 You
-             can also <a
-             
href="http://oodt.jpl.nasa.gov/download/public/Jena/jars/jena-1.6.1.jar";>fetch
-             the jar file directly</a>.
-         </li>
-       </ul>
-
-       <p>Copy these two other jars to the <code>$PS_HOME/lib</code>
-         directory.  You should now have seven jars there:
-       </p>
-
-       <source>% <b>ls -l $PS_HOME/lib</b>
-total 1580
--rw-r--r--  1 kelly  kelly   149503 28 Feb 07:28 edm-commons-2.2.5.jar
--rw-r--r--  1 kelly  kelly    43879 28 Feb 07:05 edm-query-2.0.2.jar
--rw-r--r--  1 kelly  kelly   201453 28 Feb 07:01 grid-profile-3.0.2.jar
--rw-r--r--  1 kelly  kelly  1144107 28 Feb 09:23 jena-1.6.1.jar
--rw-r--r--  1 kelly  kelly      796 28 Feb 07:07 my-handler.jar
--rw-r--r--  1 kelly  kelly     8055 28 Feb 07:28 rmi-registry-1.0.0.jar
--rw-r--r--  1 kelly  kelly    53978 28 Feb 09:20 xmlrpc-1.1.jar</source>
-
-       <p>Now, create a second shell script to make starting the
-         profile server convenient and call it
-         <code>$PS_HOME/bin/ps</code>.  It should look like this:
-       </p>
-
-       <source>#!/bin/sh
-exec java -Djava.ext.dirs=$PS_HOME/lib \
-    -Dhandlers=NullHandler \
-    jpl.eda.ExecServer \
-    jpl.eda.profile.rmi.ProfileServiceImpl \
-    urn:eda:rmi:MyProfileService</source>
-
-       <p>Make the script executable and start the profile server:</p>
-
-       <source>% <b>chmod 755 $PS_HOME/bin/ps</b>
-% <b>$PS_HOME/bin/ps</b>
-Object context ready; delegating to: 
[jpl.eda.object.jndi.RMIContext@dec8b3]</source>
-
-       <p>The profile server will start, check its
-         <code>handlers</code> property, and create an object of each
-         class named by it.  Then it'll register itself with the RMI
-         registry and wait for requests to come in from profile clients.
-       </p>
-
-      </subsection>
-
-      <subsection name="What's in a Name?">
-       <p>The profile server registers itself using a name provided
-         on the command-line, in this case,
-         <code>urn:eda:rmi:MyProfileService</code>.  Let's take apart
-         the name and see how it works.
-       </p>
-
-       <p>If you're familiar with web standards, you can see that the
-         name is a Uniform Resource Name (URN), since it starts with
-         <code>urn:</code>.  The OODT Framework uses URNs to identify
-         services and other objects.  The <code>eda:</code> tells
-         that the name is part of the Enterprise Data Architecture
-         (EDA) namespace.  (EDA was the name of a project related to
-         OODT that was merged with OODT.  For now, just always use
-         <code>eda:</code> in your URNs.)
-       </p>
-       
-       <p>Next comes <code>rmi:</code>.  This is a special flag for
-         the OODT services that tells that we're using a name of an
-         RMI-accessible object.  The OODT framework will know to use
-         an RMI registry to register the server. 
-       </p>
-
-       <p>Finally is <code>MyProfileService</code>.  This is the
-         actual name used in the RMI registry.  You can call your
-         profile server anything you want.  For example, suppose you
-         have three profile servers; one in the US, one in Canada,
-         and one in Australia.  You might name them:
-       </p>
-
-       <ul>
-         <li><code>urn:eda:rmi:US</code></li>
-         <li><code>urn:eda:rmi:Canada</code></li>
-         <li><code>urn:eda:rmi:Australia</code></li>
-       </ul>
-
-       <p>Or you might prefer to use ISO country codes.  Or you might
-         name them according to the kinds of profiles they serve,
-         such as <code>urn:eda:rmi:BiomarkerMetadata</code> or
-         <code>urn:eda:rmi:BusniessForecastMetadata</code>.
-       </p>
-
-       <p>The RMI registry will happily re-assign a name if one's
-         already in use, so when deploying your own profile (and
-         other) servers, be sure to give each one a unique name.
-       </p>
-      </subsection>
-
-      <subsection name="Querying the Profile Server">
-       <p>To query a profile server, you use the
-         <code>ProfileClient</code> class.  It provides methods to
-         contact a named profile server, performing the lookup in the
-         RMI registry, contacting the profile server, and passing in
-         queries and profile retrievals.  The
-         <code>ProfileClient</code> class is also an
-         <em>executable</em> class, making it perfect for testing a
-         new profile server from the command-line.
-       </p>
-
-       <p>Still, we'll make a script, called
-         <code>$PS_HOME/bin/pc</code> (for "profile client") to
-         execute it, though, to save from having to type hugely long
-         Java command-lines:
-       </p>
-
-       <source>#!/bin/sh
-if [ $# -ne 1 ]; then
-   echo "Usage: `basename $0` &lt;query-expression&gt;" 1&gt;&amp;2
-   exit 1
-fi
-exec java -Djava.ext.dirs=$PS_HOME/lib \
-     jpl.eda.profile.ProfileClient \
-     urn:eda:rmi:MyProfileService \
-     "$1"</source>
-
-       <p>Make this script executable and then run it:</p>
-
-       <source>% <b>chmod 755 $PS_HOME/bin/pc</b>
-% <b>$PS_HOME/bin/pc "temperature = 37"</b>
-Object context ready; delegating to: [jpl.eda.object.jndi.RMIContext@dec8b3]
-[]</source>
-
-       <p>Although it may not look spetacular, this is a success!
-         The two square brackets, <code>[]</code>, indicates the list
-         of matching profiles to our query expression,
-         <code>temperature = 37</code>.  In this case, there were no
-         matches, which is exactly what we wanted.
-       </p>
-      </subsection>
-    </section>
-
-    <section name="Conclusion">
-      <p>The Null Profile Server made sure our development
-       environment worked from end to end for creating, deploying, and
-       testing a profile handler.  Now you're ready to implement a real
-       profile handler:
-      </p>
-
-      <ul>
-       <li>Instead of returning an empty list, create a
-           <code>Profile</code> object and return it as a
-           singleton list.  See the API documentation for
-           <code>Profile</code> as well as other articles
-           for manipulating this class.
-       </li>
-       <li>Analyze the methods of the
-         <code>XMLQuery</code> class to determine the
-         query passed in from the user.  Use that information to
-         synthesize the correct <code>Profile</code>
-         object.  See the API documentation for class
-         <code>XMLQuery</code> for more information.
-       </li>
-       <li>Connecting to an external data source (such as the
-           local filesystem or a database), synthesize appropriate
-         profiles in response to queries and profile retrieval with
-         the <code>get</code> method.
-       </li>
-      </ul>
-    </section>
-  </body>
-</document>

Reply via email to