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.


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();
        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;

13 July 2012

So you think you understand optimization

James Hague suggests some elements of your application that might need to be optimized, putting aside questions of memory/storage footprint and execution speed. Three biggies of the new mobile age:
Number of disk sector writes (especially for solid-state drives).

* * *

Number of bytes of network traffic.

* * *

Number of taps/clicks it takes to accomplish a task.

01 July 2012

Show your stuff

A good piece by Eilene Zimmerman about services for displaying an online portfolio. As she notes, the idea works just as well for professions not generally considered to be "creative," like accounting or law.

I've been using Visual CV for some time now as my online shop window. I've never gotten a lead from it, as far as I know, but it's nice to have it there as a place that is completely focused on my professional work. There's more flexibility with links (I'm looking at you, LinkedIn), and with a little tweaking, you can use it to display code samples.

22 June 2012

Happy birthday, Alan

In honor of Alan Turing's centenary, Charles Severance visits Bletchley Park where Turing contributed to codebreaking in World War II, building on work by the Polish Cypher Bureau. Bletchley Park displays powered-up replicas of the hybrid electronic/electromechanical BOMBE and Colossus devices from that period.

Meanwhile, the editors of Nature evaluate Turing's legacy with a series of articles.

15 June 2012

It's a conference, hon

Registration is open for the Grace Hopper Celebration of Women Computing conference, to be held in Baltimore in October. Career fairs, workshops on leadership and personal networking skills, and over 600 speakers, including Hilary Mason, Chief Scientist at bit.ly.

14 June 2012

Let me get back to you

Blogger appears to have hosed up the formatting of posts that use <pre> and/or <code> tags.  Good thing I have a little time to clean them up.


For those of us silverbacks still making the transition to subversion, Diomidis Spinellis offers a short introduction to Git, its terminology, and its way of looking at the problem of distributed version control.

31 May 2012

Perl is still looking good to me

Though I am definitely Python-curious. I think that Eevee has told me everything I need to know about PHP.
PHP is built to keep chugging along at all costs. When faced with either doing something nonsensical or aborting with an error, it will do something nonsensical. Anything is better than nothing.

28 May 2012

01 May 2012

Pragmatic Thinking and Learning

Andy Hunt's exuberant Pragmatic Thinking and Learning: Refactor Your "Wetware" is useful collection of tips to increase creativity, exercises for improving learning performance, and ways to think about thinking.

Along the way, he debunks certain received wisdom about continuing education and professional development: he calls the traditional four days in a remote classroom cramming the latest technology "sheep-dip" training; in his words, it's an "intensive, alien, and largely toxic experience" that wears off quickly.

The book is part of Thomas and Hunt's Pragmatic Bookshelf series (of which The Pragmatic Programmer is the flagship title), so the emphasis is on just-do-it practices. For taking notes, a cheap notebook and plain text files good enough; you don't need to invest in an expensive Moleskine or complicated note-taking app if that gets in the way of taking notes. (But if something works for you, go ahead.) The underlying principle: "Capture all ideas to get more of them."

Similarly, Hunt uses a good-enough approach to modeling how human cognition works, at least so far as we understand it today. Some might find his "dual CPU" model of the brain oversimplified and off-putting, but it's in the service of illustrating the neurological dichotomy that researchers are beginning to understand. Rather than the right brain/left brain terminology that has become popular, Hunt calls the two sides ℛ-mode and 𝖫-mode (I've attempted to capture Hunt's typography with Unicode). ℛ-mode, also called rich mode, is critical for intuition and creative problem solving, while 𝖫-mode (linear mode) "gives you the power to work through the details and make it happen." A personal example from ornithology: if rich mode is like using jizz for fast identification of a flying bird, linear mode is like walking through the plumage of the bird from top to toe, worrying about the difference between "rusty" and "rufous," in order to do a subspecies ID from field marks.

Hunt's approach to illustrations aligns with his pragmatism: his graphs and figures are hand drawn, and the more effective for it.

The book's strength is also its weakness, as several ideas (Myers-Briggs typology for all us INTJs, Vipassana meditation) that warrant an entire chapter are skimmed over in a page or two. However, the references are good, and as Hunt admits,

I've barely scratched the surface on a variety of really interesting topics, and researchers are discovering new things and disproving old ideas all the time. If anything I've suggested here doesn't work out for you, don't worry about it, and move on. There's plenty more to try. (p. 248)
I found the book's heavy reliance on sidebars a smidge distracting, but that's probably just me: I feel like I don't know what to read next.

Hunt is a fan of mind maps, but I have found them to be less useful. A mind map to me is just writing your presentation's outline in a circle. On the other hand, I really like Hunt's idea of employer-facilitated study groups.

A final quibble with the graphic design: I like the readable, cushiony Bookman font that is used for body text. However, while the severely sans serif Avant Garde works well for headings and pull quotes, it's a legibility disaster to use it for URLs, as this book does in the footnotes.

30 April 2012

Fun with CQ5: 1

The code examples provided by Adobe for CQ5 developers are fine so far as they go. But I found myself exploring the territory without a map when I started prototyping code to perform a bulk import (from a legacy CMS, in my case). So I put together this toy class; it inserts a content page and text (as a parsys) at an arbitrary position in the content hierarchy.
I wrapped this functionality into a workflow process step, but it ought to work perfectly well as part of a command-line program, too. The advantage of making it a process step is that you get a session established for you, and the navigation to the insert point has been taken care of. (I haven't yet explored developing for CQ5 with standalone programs).
I created a workflow model that uses this process step, then I created an instance of the model and ran it, specifying the English > Products > Triangle page from the Geometrixx web site as the payload.
Here's the code, sanitized to remove client names and a little condensed. I'm using version 5.4.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import org.apache.sling.jcr.resource.JcrResourceConstants;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;

import com.day.cq.wcm.api.NameConstants;

        @Property(name = Constants.SERVICE_DESCRIPTION,
            value = "Makes a new tree of nodes, subordinate to the payload node, from the content of a file."),
        @Property(name = Constants.SERVICE_VENDOR, value = "Siteworx"),
        @Property(name = "process.label", value = "Make new nodes from file")})
public class PageNodesFromFile implements WorkflowProcess {

    private static final Logger log = LoggerFactory.getLogger(PageNodesFromFile.class);
    private static final String TYPE_JCR_PATH = "JCR_PATH";
* * * 
    public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args)
            throws WorkflowException {

        //get the payload
        WorkflowData workflowData = workItem.getWorkflowData();
        if (!workflowData.getPayloadType().equals(TYPE_JCR_PATH)) {
            log.warn("unusable workflow payload type: " + workflowData.getPayloadType());
        String payloadString = workflowData.getPayload().toString();

        //get the file contents
        String lipsum = null;
        try {
            BufferedReader is = new BufferedReader(new FileReader("e:\\Sandbox\\CQ5\\content.html"));
            lipsum = readerToString(is);
        catch (IOException e) {
            log.error(e.toString(), e);
        //set up some node info
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("d-MMM-yyyy-HH-mm-ss");
        String newRootNodeName = "demo-page-" + simpleDateFormat.format(new Date());
        SimpleDateFormat simpleDateFormatSpaces = new SimpleDateFormat("d MMM yyyy HH:mm:ss");
        String newRootNodeTitle = "Demo page: " + simpleDateFormatSpaces.format(new Date());
        //insert the nodes
        try {
            Node parentNode = (Node) workflowSession.getSession().getItem(payloadString);
            Node pageNode = parentNode.addNode(newRootNodeName);
            pageNode.setPrimaryType(NameConstants.NT_PAGE);                             //cq:Page
            Node contentNode = pageNode.addNode(Node.JCR_CONTENT);                      //jcr:content
            contentNode.setPrimaryType("cq:PageContent");                               //or use MigrationConstants.TYPE_CQ_PAGE_CONTENT
                                                                                        //from com.day.cq.compat.migration
            contentNode.setProperty(javax.jcr.Property.JCR_TITLE, newRootNodeTitle);    //jcr:title
                    "/apps/geometrixx/templates/contentpage");                          //cq:template
                    "geometrixx/components/contentpage");                               //sling:resourceType
            Node parsysNode = contentNode.addNode("par");
            Node textNode = parsysNode.addNode("text");
            textNode.setProperty("text", lipsum);
            textNode.setProperty("textIsRich", true);
        catch (RepositoryException e) {
            log.error(e.toString(), e);

Here's the comp text in e:\\Sandbox\\CQ5\\content.html:
Veggies sunt bona vobis, proinde vos postulo esse magis earthnut pea catsear cress sea lettuce quandong scallion rock melon seakale jícama komatsuna onion.
Bush tomato garbanzo beetroot caulie plantain sorrel swiss chard summer purslane celtuce salad seakale rutabaga radicchio lettuce spring onion groundnut soko peanut. Tigernut bitterleaf bush tomato celery corn garbanzo bamboo shoot cauliflower komatsuna cress sweet pepper mustard squash. Celtuce parsley kakadu plum coriander peanut garlic radish water chestnut tomatillo yarrow parsnip.
Squash endive collard greens tigernut bamboo shoot okra melon turnip. Rock melon amaranth ricebean pea chickpea nori bitterleaf spring onion bush tomato aubergine beetroot lotus root earthnut pea artichoke eggplant collard greens chard water spinach. Prairie turnip napa cabbage lettuce bush tomato garlic chickweed wattle seed potato lotus root pea sprouts leek kakadu plum. Radish leek green bean epazote water chestnut bamboo shoot celtuce taro tomatillo horseradish lettuce spring onion. Mustard taro prairie turnip horseradish wattle seed kohlrabi rock melon yarrow broccoli rabe fennel spinach celery collard greens gourd turnip.
Here's what the Websites window looks like after execution: cq5-demo-websites
Here's what the corresponding node looks like in CRXDE Lite: cq5-demo-crxde-lite
And here's what the page looks like in the content finder: cq5-demo-rendered
Some notes about the demonstrator code:
  • I like to use lorem ipsum-style text (I got this text from Veggie Ipsum) when I'm testing. It's always clear that you're using test data rather than a copy of something live. And in the unlikely event that your test data leaks into production, it's a lot less embarrassing to see "lorem ipsum" than "asdf jkl; asdf jkl;" or "yo mama" in 16-point type, in my opinion.
  • I incorporated a timestamp into the name and title of the content page to be inserted. That way, you can run many code and test cycles without cleaning up your repository, and you know which test was the most recently run. Added bonus: no duplicate file names, no ambiguity.
  • Adobe and Day have been inconsistent about providing constants for property values, node types, and suchlike. I used the constants that I could find, and used literal strings elsewhere.
  • I did not fill in properties like the last-modified date. In code for production I would do so.
  • I found myself confused by Node.setPrimaryType() and Node.getPrimaryNodeType(). The two methods are only rough complements; the setter takes a string but the getter returns a NodeType with various info inside it.

26 April 2012

Q and A

I invite you to participate in the development of a Q&A site dedicated to the History of Computers and Computing. The site will be part of the successful Stack Exchange network, of which Stack Overflow is the flagship, and is "for historians, enthusiasts and those who have personally experienced the evolution of computing."

One of the features of a Stack Exchange site that makes it successful is the liberal awarding of brownie points to users who constructively participate in the site. Jeff Atwood and his team have figured out the alchemy that makes a community-managed site work.

At this point, the proposed site is in the stage of soliciting committers. Follow the link below and join us!

Stack Exchange Q&A site proposal: History of Computers and Computing

25 April 2012


Today's mystery is a dusty deck submitted by sachin to Stack Overflow. He's charged with converting this old report code to SQL, but there's one problem: he can't even identify the language that the old program is coded in! Gilbert Le Blanc surmises that the JCL identifies the host computer as a Systems Engineering Laboratories/Gould/Encore machine, but there the trail ends.

19 April 2012


A really unpleasant backwards-compatibility feature of the Windows shell that I wasn't aware of.
It wasn’t until Windows NT 3.5.1 (and then Windows 95 later) that long file names were supported. Prior to this, there were a lot of limitations on what characters could be part of a filename or directory, one of those being a space.

In fact, any space in a shell command execution was seen to be an argument. This made sense at the time so you could issue a command like this:

C:\DOOM\doom.exe -episode 3

That, of course, would start Doom at episode 3. However, when Microsoft switched to Long File Names, it still had to support this type of invocation. So, the way the windows cmd.exe shell works is simple. You pass it a string like this:

C:\Program Files\id Software\Doom\Doom.exe -nomusic

And it will try to execute “C:\Program” as a file, passing it “Files\id Software\Doom\Doom.exe -nomusic” as argument to that executable. Of course, this program doesn’t exist, so it will then try to execute “C:\Program Files\id”, passing it “Software\Doom\Doom.exe -nomusic” as argument. If this doesn’t exist, it will try to execute “C:\Program Files\id Software\Doom\Doom.exe” passing in “-nomusic” as an argument. It would continue this way until a program existed and started, or until the path was depleted and no program was to be found.

11 April 2012

Work in progress

Audrey Watters accounts for the lack of success, or perceived lack of success, of the OLPC program and related education efforts. Julian Cristia et al. have recently released a study for the Inter-American Development Bank of the scheme's effectiveness in Peru. Watters:
That last (missing) piece -- training for teachers -- has long been something that gets overlooked when it comes to ed-tech initiatives no matter the location, Peru or the U.S. It is almost as if we believe we can simply parachute technology in to a classroom and expect everyone to just pick it up, understand it, use it, hack it, and prosper.
The Code Project

31 March 2012

Delayed mercury

Charles Severance visits the Monash Museum of Computer History and talks to Judy Sheard and Chris Avram. The museum is on the Caulfield campus of Monash University in Melbourne, Victoria, and hosts CSIRAC, Australia's first digital computer and the fourth stored-program computer in the world.

30 March 2012


I've started chipping a little content into Stack Overflow, and have accumulated sufficient reputation points that I can upvote answers. There's a lot of work that could be done in the tag wiki—that could keep me busy.

29 March 2012

Still going

Benj Edwards reports for PCWorld on vintage systems that are still in production, running inventory, controlling aircraft systems, generating financial statements. The jewel of this (popup-heavy) report is an plugboard-programmed IBM 402 tabulator in service at a Texas industrial filter factory.

Paul Ceruzzi and the IT History Society blog

22 February 2012

News item

Evan Sandhaus announces the New York Times's implementation of rNews, a semantic markup scheme for news articles. Curiously, the blog post itself doesn't carry the markup.

18 February 2012

Home base

booting upBack at Siteworx Reston after an extended stay onsite, and after a couple of moves and cubicle reconfigurations, here's what most of my work surface looks like now. Oh, and after receipt of peachy Valentine's Day flowers from Leta.

A really nice chair, a big Kensington trackball that they don't make anymore, a monitor and a half (the laptop), and a good-sized shelf for books above. Need to do something about that tangle of USB cables.

08 February 2012

Keep trying

Jairaj Bhattacharya et al. give poor marks to DataWind's Aakash-1 tablet, the latest in a series of low cost computers designed for students in developing countries. The expected price point for this device, which is more than a prototype but not yet generally available, is ₹2500 (about $50).
Its limited battery life—a maximum of 2.5 hours, which falls to 1 hour and 20 minutes with video or other applications running—is disappointing for a device that is supposed to be used in villages where access to electricity is sporadic at best.

30 January 2012

Learning to COPE

Scott M. Fulton, III interviews Daniel Jacobson in support of Dan's new O'Reilly book APIs: A Strategy Guide, co-authored with Greg Brail and Dan Wood.

26 January 2012

Had we but money enough and time

Plan 28, brainchild of John Graham-Cumming and Doron Swade, and with the cooperation of London's Science Museum and the Computer Conservation Society, has begun the process of building Charles Babbage's Analytical Engine. Once Babbage's plans are digitized, the first big task is to figure out which of his (incomplete) designs to build.

24 January 2012

No vanilla, just chocolate

I am sure that one of my upcoming projects can find a use for this: Matthew DeLambo introduces ICE, a plugin for TinyMCE and WordPress that tracks changes. The post also mentions the DOM Range feature, which also might have helped us out on some previous work.

18 January 2012

Good advice

Two related links via The Code Project: Jennifer Lindner interviews two instructors from Girl Develop It, which offers workshops in HTML/CSS, JavaScript/jQuery, Ruby on Rails, and other topics in six cities worldwide; STEMINIST is a Storify-style aggregator of news about women in science, technology, engineering, and mathematics.

Izzy Johnson of Girl Develop It:

I would advise anyone who wants to be involved in instruction that the first issue you have to address is never about the language. Not “What is a variable?” or “What does a for loop do?” The first issue you have to address is making sure each person in the room believes that they are capable of learning everything you are about to tell them. From your curriculum, to your slides, to your attitude–create a class that builds confidence at every step.

09 January 2012

Looking for an NB compiler

I decided to follow the single-letter style and called it C, leaving open the question whether the name represented a progression through the alphabet or through the letters in BCPL.
Via The Code Project, in a paper from 1993, Dennis Ritchie describes the evolution of C from its predecessor languages.