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.nuxeo.ecm.automation.client.jaxrs.spi.JsonMarshaller;
024import org.nuxeo.ecm.automation.client.model.Document;
025import org.nuxeo.ecm.automation.client.model.PropertyList;
026import org.nuxeo.ecm.automation.client.model.PropertyMap;
027import org.nuxeo.ecm.automation.client.model.PropertyMapSetter;
028
029import com.fasterxml.jackson.core.JsonGenerator;
030import com.fasterxml.jackson.core.JsonParser;
031import com.fasterxml.jackson.core.JsonToken;
032
033/**
034 * @author matic
035 */
036public class DocumentMarshaller implements JsonMarshaller<Document> {
037
038    @Override
039    public String getType() {
040        return "document";
041    }
042
043    @Override
044    public Class<Document> getJavaType() {
045        return Document.class;
046    }
047
048    @Override
049    public Document read(JsonParser jp) throws IOException {
050        return readDocument(jp);
051    }
052
053    protected static Document readDocument(JsonParser jp) throws IOException {
054        String uid = null;
055        String type = null;
056        String path = null;
057        String state = null;
058        String versionLabel = null;
059        String isCheckedOut = null;
060        String lockCreated = null;
061        String lockOwner = null;
062        String repository = null;
063        PropertyList facets = null;
064        String changeToken = null;
065        JsonToken tok = jp.nextToken();
066        PropertyMap props = new PropertyMap();
067        PropertyMapSetter propsSetter = new PropertyMapSetter(props);
068        PropertyMap contextParameters = new PropertyMap();
069        while (tok != null && tok != JsonToken.END_OBJECT) {
070            String key = jp.getCurrentName();
071            tok = jp.nextToken();
072            if (key.equals("uid")) {
073                uid = jp.getText();
074            } else if (key.equals("path")) {
075                path = jp.getText();
076            } else if (key.equals("type")) {
077                type = jp.getText();
078            } else if (key.equals("state")) {
079                state = jp.getText();
080            } else if (key.equals("versionLabel")) {
081                versionLabel = jp.getText();
082            } else if (key.equals("isCheckedOut")) {
083                isCheckedOut = jp.getText();
084            } else if (key.equals("lock")) {
085                if (!JsonToken.VALUE_NULL.equals(jp.getCurrentToken())) {
086                    String[] lock = jp.getText().split(":");
087                    lockOwner = lock[0];
088                    lockCreated = lock[1];
089                }
090            } else if (key.equals("lockCreated")) {
091                lockCreated = jp.getText();
092            } else if (key.equals("lockOwner")) {
093                lockOwner = jp.getText();
094            } else if (key.equals("repository")) {
095                repository = jp.getText();
096            } else if (key.equals("title")) {
097                propsSetter.set("dc:title", jp.getText());
098            } else if (key.equals("lastModified")) {
099                propsSetter.set("dc:modified", jp.getText());
100            } else if (key.equals("properties")) {
101                readProperties(jp, props);
102            } else if (key.equals("facets")) {
103                facets = readArrayProperty(jp);
104            } else if (key.equals("changeToken")) {
105                changeToken = jp.getText();
106            } else if (key.equals("contextParameters")) {
107                readProperties(jp, contextParameters);
108            } else {
109                // do skip unknown keys
110                jp.skipChildren();
111            }
112            tok = jp.nextToken();
113        }
114        if (tok == null) {
115            throw new IllegalArgumentException("Unexpected end of stream.");
116        }
117        return new Document(uid, type, facets, changeToken, path, state, lockOwner, lockCreated, repository,
118                versionLabel, isCheckedOut, props, contextParameters);
119    }
120
121    protected static void readProperties(JsonParser jp, PropertyMap props) throws IOException {
122        PropertyMapSetter setter = new PropertyMapSetter(props);
123        JsonToken tok = jp.nextToken();
124        while (tok != null && tok != JsonToken.END_OBJECT) {
125            String key = jp.getCurrentName();
126            tok = jp.nextToken();
127            if (tok == JsonToken.START_ARRAY) {
128                setter.set(key, readArrayProperty(jp));
129            } else if (tok == JsonToken.START_OBJECT) {
130                setter.set(key, readObjectProperty(jp));
131            } else if (tok == JsonToken.VALUE_NULL) {
132                setter.set(key, (String) null);
133            } else {
134                setter.set(key, jp.getText());
135            }
136            tok = jp.nextToken();
137        }
138        if (tok == null) {
139            throw new IllegalArgumentException("Unexpected end of stream.");
140        }
141    }
142
143    protected static PropertyMap readObjectProperty(JsonParser jp) throws IOException {
144        PropertyMap map = new PropertyMap();
145        readProperties(jp, map);
146        return map;
147    }
148
149    protected static PropertyList readArrayProperty(JsonParser jp) throws IOException {
150        PropertyList list = new PropertyList();
151        JsonToken tok = jp.nextToken();
152        while (tok != JsonToken.END_ARRAY) {
153            if (tok == JsonToken.START_ARRAY) {
154                list.add(readArrayProperty(jp));
155            } else if (tok == JsonToken.START_OBJECT) {
156                list.add(readObjectProperty(jp));
157            } else {
158                list.add(jp.getText());
159            }
160            tok = jp.nextToken();
161        }
162        return list;
163    }
164
165    @Override
166    public void write(JsonGenerator jg, Object value) throws IOException {
167        // TODO: extend the server json API to allow for document refs passed as
168        // JSON data-structures instead of the input ref microsyntax used by
169        throw new UnsupportedOperationException();
170    }
171
172}