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