001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     matic
011 */
012package org.nuxeo.ecm.automation.client.jaxrs.spi.marshallers;
013
014import java.io.IOException;
015
016import org.codehaus.jackson.JsonGenerator;
017import org.codehaus.jackson.JsonParser;
018import org.codehaus.jackson.JsonToken;
019import org.nuxeo.ecm.automation.client.jaxrs.spi.JsonMarshaller;
020import org.nuxeo.ecm.automation.client.model.Document;
021import org.nuxeo.ecm.automation.client.model.PropertyList;
022import org.nuxeo.ecm.automation.client.model.PropertyMap;
023import org.nuxeo.ecm.automation.client.model.PropertyMapSetter;
024
025/**
026 * @author matic
027 */
028public class DocumentMarshaller implements JsonMarshaller<Document> {
029
030    @Override
031    public String getType() {
032        return "document";
033    }
034
035    @Override
036    public Class<Document> getJavaType() {
037        return Document.class;
038    }
039
040    @Override
041    public Document read(JsonParser jp) throws IOException {
042        return readDocument(jp);
043    }
044
045    protected static Document readDocument(JsonParser jp) throws IOException {
046        String uid = null;
047        String type = null;
048        String path = null;
049        String state = null;
050        String versionLabel = null;
051        String isCheckedOut = null;
052        String lockCreated = null;
053        String lockOwner = null;
054        String repository = null;
055        PropertyList facets = null;
056        String changeToken = null;
057        JsonToken tok = jp.nextToken();
058        PropertyMap props = new PropertyMap();
059        PropertyMapSetter propsSetter = new PropertyMapSetter(props);
060        PropertyMap contextParameters = new PropertyMap();
061        while (tok != null && tok != JsonToken.END_OBJECT) {
062            String key = jp.getCurrentName();
063            tok = jp.nextToken();
064            if (key.equals("uid")) {
065                uid = jp.getText();
066            } else if (key.equals("path")) {
067                path = jp.getText();
068            } else if (key.equals("type")) {
069                type = jp.getText();
070            } else if (key.equals("state")) {
071                state = jp.getText();
072            } else if (key.equals("versionLabel")) {
073                versionLabel = jp.getText();
074            } else if (key.equals("isCheckedOut")) {
075                isCheckedOut = jp.getText();
076            } else if (key.equals("lock")) {
077                if (!JsonToken.VALUE_NULL.equals(jp.getCurrentToken())) {
078                    String[] lock = jp.getText().split(":");
079                    lockOwner = lock[0];
080                    lockCreated = lock[1];
081                }
082            } else if (key.equals("lockCreated")) {
083                lockCreated = jp.getText();
084            } else if (key.equals("lockOwner")) {
085                lockOwner = jp.getText();
086            } else if (key.equals("repository")) {
087                repository = jp.getText();
088            } else if (key.equals("title")) {
089                propsSetter.set("dc:title", jp.getText());
090            } else if (key.equals("lastModified")) {
091                propsSetter.set("dc:modified", jp.getText());
092            } else if (key.equals("properties")) {
093                readProperties(jp, props);
094            } else if (key.equals("facets")) {
095                facets = readArrayProperty(jp);
096            } else if (key.equals("changeToken")) {
097                changeToken = jp.getText();
098            } else if (key.equals("contextParameters")) {
099                readProperties(jp, contextParameters);
100            } else {
101                // do skip unknown keys
102                jp.skipChildren();
103            }
104            tok = jp.nextToken();
105        }
106        if (tok == null) {
107            throw new IllegalArgumentException("Unexpected end of stream.");
108        }
109        return new Document(uid, type, facets, changeToken, path, state, lockOwner, lockCreated, repository,
110                versionLabel, isCheckedOut, props, contextParameters);
111    }
112
113    protected static void readProperties(JsonParser jp, PropertyMap props) throws IOException {
114        PropertyMapSetter setter = new PropertyMapSetter(props);
115        JsonToken tok = jp.nextToken();
116        while (tok != null && tok != JsonToken.END_OBJECT) {
117            String key = jp.getCurrentName();
118            tok = jp.nextToken();
119            if (tok == JsonToken.START_ARRAY) {
120                setter.set(key, readArrayProperty(jp));
121            } else if (tok == JsonToken.START_OBJECT) {
122                setter.set(key, readObjectProperty(jp));
123            } else if (tok == JsonToken.VALUE_NULL) {
124                setter.set(key, (String) null);
125            } else {
126                setter.set(key, jp.getText());
127            }
128            tok = jp.nextToken();
129        }
130        if (tok == null) {
131            throw new IllegalArgumentException("Unexpected end of stream.");
132        }
133    }
134
135    protected static PropertyMap readObjectProperty(JsonParser jp) throws IOException {
136        PropertyMap map = new PropertyMap();
137        readProperties(jp, map);
138        return map;
139    }
140
141    protected static PropertyList readArrayProperty(JsonParser jp) throws IOException {
142        PropertyList list = new PropertyList();
143        JsonToken tok = jp.nextToken();
144        while (tok != JsonToken.END_ARRAY) {
145            if (tok == JsonToken.START_ARRAY) {
146                list.add(readArrayProperty(jp));
147            } else if (tok == JsonToken.START_OBJECT) {
148                list.add(readObjectProperty(jp));
149            } else {
150                list.add(jp.getText());
151            }
152            tok = jp.nextToken();
153        }
154        return list;
155    }
156
157    @Override
158    public void write(JsonGenerator jg, Object value) throws IOException {
159        // TODO: extend the server json API to allow for document refs passed as
160        // JSON data-structures instead of the input ref microsyntax used by
161        throw new UnsupportedOperationException();
162    }
163
164}