SELECT ?mbox1, ?mbox2, ?uri
WHERE
(foaf::depiction ?x ?img)
(foaf::depiction ?z ?img)
(foaf::thumbnail ?img ?uri)
(foaf::mbox ?x ?mbox1)
(foaf::mbox ?z ?mbox2)
USING foaf for http://xmlns.com/foaf/0.1/
This (essentially) returns a table where each row contains two
mailboxes and the uri of a (thumbnail of) an image depicting
each of the people with the mailboxes. For example:
| mbox1 | mbox2 | uri |
|---|---|---|
| mailto:alice@example.com | mailto:bob@example.com | http://example.com/images/aliceandbob_small.png |
| mailto:alice@example.com | mailto:bob@example.com | http://example.com/images/aliceandbobagain_small.png |
| mailto:bob@example.com | mailto:bob@example.com | http://example.com/images/bob_small.png |
| mailto:claire@example.com | mailto:alice@example.com | http://example.com/images/claireandalice_small.png |
| ... | ... | ... |
There are two things to note here: people can be codepicted in more then one image; and people are codepicted with themselves in any image in which they appear.
The latter is something to watch out for: since such entries are irrelevant for paths we don't use them. The former is quite important for our model - we store all images depicting the same two people.
Note: TNode also holds knows when it has been visited in the paths search (see below).
Currently sending a getLabel() message to a TEdge returns images at random.
TGraph provides an easy way to add mbox1-mbox2-image triples to the graph. This does the necessary lookups and also ignores the troublesome mbox-mbox(again)-image triples.
Graphically the procedure looks like this:
At the end parents is {E} and is linked to no unvisited nodes, so children is empty and we finish. leaves = {C, D, B, F, H, G, E} at the end.
The code is pretty simple. We use a class TElement.java to represent an element of the tree (TElements are actually used in the parent/children arrays, rather than nodes). A TElement contains a parent TElement (null for the root), a TNode, and a TEdge (which connects the TElement to its parent, null for the root).
public Vector findShortestPathsFromNode(TNode root)
{
// Clear graph for search
for (Iterator nodeIterator = nodes.iterator();
nodeIterator.hasNext();)
{
TNode node = (TNode) nodeIterator.next();
node.setVisited(false);
}
// But (of course) we start with a node, so let's say it's
// been visited
root.setVisited(true);
// Set up the root of the tree
TElement treeRoot = new TElement(root, null);
// Set up parents vector (just treeRoot) and leaves (empty)
Vector parents = new Vector();
parents.add(treeRoot);
Vector leaves = new Vector();
// indicates whether to keep going
boolean continuing = true;
while (continuing)
{
Vector children = new Vector();
continuing = false;
// Iterate through parents
for (Iterator parentIterator = parents.iterator();
parentIterator.hasNext();)
{
TElement parent = (TElement)
parentIterator.next();
TNode parentNode = parent.node();
// Iterate through edges from parent
for (Iterator edgeIterator =
parentNode.getEdges().iterator();
edgeIterator.hasNext();)
{
TEdge edge = (TEdge)
edgeIterator.next();
TNode childNode =
edge.getOtherNode(parentNode);
if (childNode.notVisited())
{
childNode.setVisited(true);
TElement child = new
TElement(childNode,
parent, edge);
leaves.add(child);
children.add(child);
continuing = true;
}
}
}
parents = children;
}
return leaves;
}
Simple enough I hope.
Improvements: