07 January 2013

But still cute

Aaron Souppouris gets a quick look at the XO-4 convertible at CES. Dan Lyons isn't impressed.
We now have an actual hundred-dollar computer. Loads of them, in fact. They're called smartphones and tablets. Many can be had for well under a hundred dollars.

This is more than can be said for the XO machine, which even now, eight years after [Nicholas] Negroponte first dreamed up the idea, still costs a lot more than a hundred bucks.

That's right. Nearly a decade into this they still can't hit their original price point.

20 December 2012

Fun with CQ5: 3

My manager referred me to a couple of posts on Jörg Hoh's blog of tips and tricks for CQ5. And from there I learned that Adobe offers two certification courses in CQ5.5. It's always nice to have a new certification to add to your resume. But I should probably wait to sit for the Component Developer exam until I finish the new project I'm starting in January, because my experience to this point has been with 5.4.

19 October 2012

Spoiler alert: we drop the bomb

An adorable gallery of improbable Hollywood computers doing improbable things. The star of the piece is a decommissioned IBM AN/FSQ-7 Combat Direction Central, part of the SAGE radar defenses of the Eisenhower-Kennedy era—you know, the times back when the operator's console had an integrated ashtray. Parts of the defanged AN/FSQ-7, Q7 for short and cute, appeared with O. J. Simpson, Woody Allen, and babealicous scientist Lee Meriwether—but not with Peter Sellars in Dr. Strangelove. That part was filled by an IBM 7090/94.
...we find it rather amusing that in the one movie where the AN/FSQ-7 would make perfect sense, you don't find the AN/FSQ-7.
At least it was one the scientific systems, not one of IBM's business mainframes.

ᔥ Bits

12 September 2012

Fun with CQ5: 2

We follow Adobe's recommendation to use the tag structure to represent menu navigation. Thus, pages can be organized in the content tree the way that is convenient for authors to work (or perhaps to enforce some design restrictions by template), while menus can evolve flexibly in response to usability testing or can differ depending on platform (desktop vs. mobile).

So to render a menu, it's a typical coding pattern to walk a subtree of tags, and for each one, find its corresponding web page (Node) and render its hyperlink. The only tricky bit is that com.day.cq.tagging.Tag.find() returns both Nodes that are explcitly marked with the specified tag as well as Nodes that are only subordinate to a Node that is assigned the tag. A lot of the time, you just want Nodes of the first kind.

We had been using a scheme that matched the Node's navigation title to the tag's title, but that pattern broke down when authors started designing menu items with duplicate names. (And there were other wrinkles.) So, after some desperate Friday afternoon whiteboard sketching, I realized that we could inquire of each candidate Node what tags were assigned to it explicitly, and test for an exact match of TagIDs. And I cooked up the following method, stripped of exception handling, debugging logic, and a little project-specific stuff. The cq:tags property is multi-valued, so there's a little more messy object navigation than you might expect.

import com.day.cq.tagging.Tag;
import java.util.Iterator;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.Value;
import org.apache.sling.api.resource.Resource;

* * * 

    /**
     * Returns the node tagged with the specified tag; if there is more than one such node, returns
     * one of them arbitrarily.  The node must have the tag assigned directly to it as a property;
     * nodes that are tagged by inheritance in the content tree are ignored.
     * @param tag
     * @return node: the node tagged with the specified tag, or null
     */
    public static Node getMatchingNode(Tag tag) {
        Node matchingNode = null;
        Iterator<Resource> relatedNodes = tag.find();
        outer:
        while (relatedNodes.hasNext() && matchingNode == null) {
            Node node = relatedNodes.next().adaptTo(Node.class);
            PropertyIterator tagIds = node.getProperties("cq:tags");
            while (tagIds.hasNext()) {
                Property property = tagIds.nextProperty();
                Value values[] = property.getValues();
                for (Value value : values) {
                    String id = value.getString();
                    if (id.equals(tag.getTagID())) {
                        matchingNode = node;
                        break outer;
                    }
                }
            }
        }
        return matchingNode;
    }