Package com.ettrema.json

Source Code of com.ettrema.json.JsonPropFindHandler

package com.ettrema.json;

import com.bradmcevoy.http.CollectionResource;
import com.bradmcevoy.http.PropFindableResource;
import com.bradmcevoy.http.Range;
import com.bradmcevoy.http.Resource;
import com.bradmcevoy.http.exceptions.NotAuthorizedException;
import com.bradmcevoy.http.values.ValueAndType;
import com.bradmcevoy.http.webdav.PropFindPropertyBuilder;
import com.bradmcevoy.http.webdav.PropFindRequestFieldParser.ParseResult;
import com.bradmcevoy.http.webdav.PropFindResponse;
import com.bradmcevoy.http.webdav.ResourceTypeHelper;
import com.bradmcevoy.http.webdav.WebDavProtocol;
import com.bradmcevoy.http.webdav.WebDavResourceTypeHelper;
import com.bradmcevoy.property.PropertySource;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.namespace.QName;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import net.sf.json.util.CycleDetectionStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* @author brad
*/
public class JsonPropFindHandler {

    private static final Logger log = LoggerFactory.getLogger(JsonPropFindHandler.class);
    private final PropFindPropertyBuilder propertyBuilder;
    private final Helper helper;

    public JsonPropFindHandler(PropFindPropertyBuilder propertyBuilder) {
        this.propertyBuilder = propertyBuilder;
        helper = new Helper();
    }

    public JsonPropFindHandler(List<PropertySource> propertySources) {
        ResourceTypeHelper resourceTypeHelper = new WebDavResourceTypeHelper();
        this.propertyBuilder = new PropFindPropertyBuilder(propertySources);
        helper = new Helper();
    }

    public void sendContent(PropFindableResource wrappedResource, String encodedUrl, OutputStream out, Range range, Map<String, String> params, String contentType) throws IOException, NotAuthorizedException {
        log.debug("sendContent: " + encodedUrl);
        JsonConfig cfg = new JsonConfig();
        cfg.setIgnoreTransientFields(true);
        cfg.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);

        JSON json;
        Writer writer = new PrintWriter(out);
        String[] arr;
        if (propertyBuilder == null) {
            if (wrappedResource instanceof CollectionResource) {
                List<? extends Resource> children = ((CollectionResource) wrappedResource).getChildren();
                json = JSONSerializer.toJSON(toSimpleList(children), cfg);
            } else {
                json = JSONSerializer.toJSON(toSimple(wrappedResource), cfg);
            }
        } else {
            // use propfind handler
            String sFields = params.get("fields");
            Set<QName> fields = new HashSet<QName>();
            Map<QName, String> aliases = new HashMap<QName, String>();
            if (sFields != null && sFields.length() > 0) {
                arr = sFields.split(",");
                for (String s : arr) {
                    parseField(s, fields, aliases);
                }
            }

            String sDepth = params.get("depth");
            int depth = 1;
            if (sDepth != null && sDepth.trim().length() > 0) {
                depth = Integer.parseInt(sDepth);
            }

            String href = encodedUrl.replace("/_DAV/PROPFIND", "");
            log.debug("prop builder: " + propertyBuilder.getClass());
            ParseResult parseResult = new ParseResult(false, fields);
            List<PropFindResponse> props = propertyBuilder.buildProperties(wrappedResource, depth, parseResult, href);

            String where = params.get("where");
            filterResults(props, where);

            List<Map<String, Object>> list = helper.toMap(props, aliases);
            json = JSONSerializer.toJSON(list, cfg);
        }
        json.write(writer);
        writer.flush();
    }

    /**
     * Parse the given field and populate the given maps
     *
     * A field may be in the following forms
     * - foo
     * - DAV:foo
     * - DAV:foo>bar
     * - foo>bar
     *
     * The first is just a property named foo.
     * The second is a property called foo in the namespace DAV
     * The third includes an alias so the property is returned with the name "bar" in the json object
     * The final shows that an alias can be used without a namespace
     *
     * @param field
     * @param fields
     */
    void parseField(String field, Set<QName> fields, Map<QName, String> aliases) {
        String alias = null;
        if (field.contains(">")) {
            int pos = field.indexOf(">");
            alias = field.substring(pos + 1);
            field = field.substring(0, pos);
        }
        QName qn = parseQName(field);
        //log.debug("field: " + qn);
        fields.add(qn);
        if (alias != null) {
            aliases.put(qn, alias);
        }
    }

    private QName parseQName(String field) {
        if (field.contains(":")) {
            // name is of form uri:local  E.g. MyDav:authorName
            String[] parts = field.split(":");
            String nsUri = parts[0];
            String localName = parts[1];
            return new QName(nsUri, localName);
        } else {
            // name is simple form E.g. displayname, default nsUri to DAV
            return new QName(WebDavProtocol.NS_DAV.getName(), field);
        }

    }

    private List<SimpleResource> toSimpleList(List<? extends Resource> list) {
        List<SimpleResource> simpleList = new ArrayList<SimpleResource>(list.size());
        for (Resource r : list) {
            simpleList.add(toSimple(r));
        }
        return simpleList;
    }

    private SimpleResource toSimple(Resource r) {
        return new SimpleResource(r);
    }

    /**
     * If the where argument is given, removes results where it does not
     * evaluate to true
     *
     * If the given where argument starts with ! the condition is negated
     *
     * @param results
     * @param where
     */
    private void filterResults(List<PropFindResponse> results, String where) {
        if (where != null && where.length() > 0) {
            boolean negate = where.startsWith("!");
            if (negate) {
                where = where.substring(1);
            }
            ValueAndType prop;
            QName qnWhere = parseQName(where);
            Iterator<PropFindResponse> it = results.iterator();
            boolean removeValue = negate;
            while (it.hasNext()) {
                PropFindResponse result = it.next();
                boolean isTrue = eval(qnWhere, result);
                // eg !iscollection for a folder -> false == false = true, so remove
                // eg !iscollection for a file -> true == false = false, dont remove
                // eg iscollection for a folder -> false == true = false, so dont remove
                if (isTrue == removeValue) {
                    it.remove();
                }
            }
        }
    }

    /**
     * Find a boolean value from the given propery name on the propfind
     * result.
     *
     * Absense of the property, or a value which
     * cannot be interpreted as boolean, implies false.
     *
     * @param qnWhere
     * @param result
     * @return
     */
    private boolean eval(QName qnWhere, PropFindResponse result) {
        ValueAndType prop = result.getKnownProperties().get(qnWhere);
        if (prop != null) {
            Object val = prop.getValue();
            if (val != null && val instanceof Boolean) {
                Boolean b = (Boolean) val;
                return b;
            } else {
                return false;
            }
        } else {
            return false;
        }

    }

    public class SimpleResource {

        private final Resource r;

        public SimpleResource(Resource r) {
            this.r = r;
        }

        public String getName() {
            return r.getName();
        }

        public Date getModifiedDate() {
            return r.getModifiedDate();
        }
    }

    class Helper {

        private List<Map<String, Object>> toMap(List<PropFindResponse> props, Map<QName, String> aliases) {
            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
            Object val;
            for (PropFindResponse prop : props) {
                Map<String, Object> map = new HashMap<String, Object>();
                list.add(map);
                for (Entry<QName, ValueAndType> p : prop.getKnownProperties().entrySet()) {
                    String name = aliases.get(p.getKey());
                    if (name == null) {
                        name = p.getKey().getLocalPart();
                    }
                    val = p.getValue().getValue();
                    map.put(name, val);
                }
            }
            return list;
        }
    }
}
TOP

Related Classes of com.ettrema.json.JsonPropFindHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.