oodt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mattm...@apache.org
Subject [16/88] [abbrv] [partial] oodt git commit: Record change for OODT-836, OODT-837.
Date Mon, 17 Jul 2017 23:05:31 GMT
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="Sean.Kelly@jpl.nasa.gov">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="Sean.Kelly@jpl.nasa.gov">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>


Mime
View raw message