com.scit.sling.test.MockResourceFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.scit.sling.test.MockResourceFactory.java

Source

/**
 * Copyright (c) 2007-2011 Southern Cross IT. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */
package com.scit.sling.test;

import static org.apache.commons.lang.StringUtils.isEmpty;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;

import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * Factory for creating {@link MockResource}/{@link MockResourceResolver}.
 */
public class MockResourceFactory {
    /**
     * Helper factory method that does:<br>
     * <code>
     * ResourceNode root = loadRepositoryFromJson(basePath, in);<br>
      * return buildMockRepository(root);
     * </code>
     * 
     * @param basePath the parent path of this node (blank if it's meant to be the root)
     * @param in the input stream to load the JSON representation
     * 
     * @return 
     * @throws JsonParseException
     * @throws IOException
     */
    public static MockResourceResolver buildMockRepositoryJson(String basePath, InputStream in)
            throws JsonParseException, IOException {
        ResourceNode root = loadRepositoryFromJson(basePath, in);
        return buildMockRepository(root);
    }

    /**
     * Build a {@link MockResourceResolver} with all {@link MockResource} and {@link MockValueMap} setup from a {@link ResourceNode} that
     * has possibly been loaded from {@link #loadRepositoryFromJson(String, InputStream)} or built manually<br>
     * 
     * @param baseNode
     * @return
     */
    public static MockResourceResolver buildMockRepository(ResourceNode baseNode) {
        MockResourceResolver resolver = new MockResourceResolver();
        addResource(baseNode, buildResource(resolver, baseNode), resolver);
        return resolver;
    }

    private static MockResourceResolver addResource(ResourceNode baseNode, MockResource baseResource,
            MockResourceResolver resolver) {
        LinkedList<Resource> children = new LinkedList<Resource>();
        for (ResourceNode child : baseNode.getChildren()) {
            MockResource childResource = buildResource(resolver, child);
            resolver.addResource(childResource);
            children.add(childResource);
            addResource(child, childResource, resolver);
        }
        resolver.addResource(baseResource);
        resolver.addChildren(baseResource, children);
        return resolver;
    }

    private static MockResource buildResource(MockResourceResolver resolver, ResourceNode node) {
        ValueMap properties = node.getProperties();
        String type = properties.get("sling:resourceType", String.class);
        if (isEmpty(type)) {
            type = properties.get("jcr:primaryType", "");
        }
        MockResource r = new MockResource(resolver, node.getPath(), type);
        r.getMockAdaptable().addAdaptable(ValueMap.class, properties);
        return r;
    }

    /**
     * Build a {@link MockResourceResolver} with all {@link MockResource} and {@link MockValueMap}.<br>
     * The format of the JSON input is compatible with the Apache Sling json representations of the JCR, i.e. 
     * <blockquote>curl -s -u admin:admin http://localhost:8080/content/path/to/node.infinity.json</blockquote>
     * 
     * @param basePath the parent path of this node (blank if it's meant to be the root)
     * @param in the input stream to load the JSON representation
     * 
     * @return 
     * @throws JsonParseException
     * @throws IOException
     */
    public static ResourceNode loadRepositoryFromJson(String basePath, InputStream in)
            throws JsonParseException, IOException {
        JsonFactory jsonFactory = new JsonFactory();
        JsonParser jp = jsonFactory.createJsonParser(in);
        ResourceNode root = new ResourceNode(StringUtils.substringBeforeLast(basePath, "/"),
                StringUtils.substringAfterLast(basePath, "/"));
        JsonToken token = jp.nextToken();
        if (token == JsonToken.START_OBJECT) {
            parseJsonObject(root, jp);
        }
        return root;
    }

    private static ResourceNode parseJsonObject(ResourceNode context, JsonParser jp)
            throws JsonParseException, IOException {
        JsonToken token;
        String fieldname = "";
        while ((token = jp.nextToken()) != JsonToken.END_OBJECT) {
            switch (token) {
            case START_OBJECT:
                ResourceNode child = new ResourceNode(context, fieldname);
                context.addChild(child);
                parseJsonObject(child, jp);
                break;
            case FIELD_NAME:
                fieldname = jp.getCurrentName();
                break;
            case START_ARRAY:
                LinkedList<Object> array = new LinkedList<Object>();
                while ((token = jp.nextToken()) != JsonToken.END_ARRAY) {
                    array.add(parseValue(token, jp));
                }
                context.addProperty(fieldname, array.toArray());
                break;
            default:
                if (token.isScalarValue()) {
                    context.addProperty(fieldname, parseValue(token, jp));
                }
                // log.warnd ???
            }
        }
        return context;
    }

    private static Object parseValue(JsonToken token, JsonParser jp) throws JsonParseException, IOException {
        if (token.isNumeric()) {
            switch (jp.getNumberType()) {
            case INT:
                return jp.getIntValue();
            case LONG:
                return jp.getLongValue();
            case BIG_INTEGER:
                return jp.getBigIntegerValue();
            case FLOAT:
                return jp.getFloatValue();
            case DOUBLE:
                return jp.getDoubleValue();
            case BIG_DECIMAL:
                return jp.getDecimalValue();
            default:
                //log.warn("Don't know how to handle '" + fieldname + "' of type " + jp.getNumberType() + " with value '" + jp.getText() + "'");
                return dateOrText(jp.getText());
            }
        }
        switch (token) {
        case VALUE_FALSE:
        case VALUE_TRUE:
            return jp.getBooleanValue();
        case VALUE_STRING:
            return dateOrText(jp.getText());
        case VALUE_NULL:
            break;
        }
        return dateOrText(jp.getText());
    }

    private static Object dateOrText(String text) {
        try {
            return DATE_TIME_FORMAT.parseDateTime(text.replaceAll(" [A-Z][A-Z][A-Z]([\\+\\-])", " $1"));
        } catch (IllegalArgumentException e) {
            return text;
        }
    }

    public static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormat
            .forPattern("EEE MMM dd YYYY HH:mm:ss Z");
}