001/*
002 * (C) Copyright 2016 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 *     Nuxeo
018 */
019
020package org.nuxeo.ecm.user.center.profile.rest;
021
022import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
023import static org.nuxeo.ecm.core.io.marshallers.json.document.DocumentModelJsonWriter.ENTITY_TYPE;
024import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON;
025import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE;
026import static org.nuxeo.ecm.user.center.profile.UserProfileConstants.USER_PROFILE_AVATAR_FIELD;
027import static org.nuxeo.ecm.user.center.profile.UserProfileConstants.USER_PROFILE_BIRTHDATE_FIELD;
028import static org.nuxeo.ecm.user.center.profile.UserProfileConstants.USER_PROFILE_PHONENUMBER_FIELD;
029import static org.nuxeo.ecm.user.center.profile.UserProfileConstants.USER_PROFILE_SCHEMA;
030
031import java.io.Closeable;
032import java.io.IOException;
033import java.io.OutputStream;
034import java.io.Serializable;
035import java.util.GregorianCalendar;
036
037import javax.inject.Inject;
038
039import org.apache.commons.lang3.time.FastDateFormat;
040import org.codehaus.jackson.JsonGenerator;
041import org.nuxeo.ecm.core.api.Blob;
042import org.nuxeo.ecm.core.api.DocumentModel;
043import org.nuxeo.ecm.core.api.NuxeoPrincipal;
044import org.nuxeo.ecm.core.api.model.Property;
045import org.nuxeo.ecm.core.io.download.DownloadService;
046import org.nuxeo.ecm.core.io.marshallers.json.OutputStreamWithJsonWriter;
047import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher;
048import org.nuxeo.ecm.core.io.registry.Writer;
049import org.nuxeo.ecm.core.io.registry.context.RenderingContext;
050import org.nuxeo.ecm.core.io.registry.reflect.Setup;
051import org.nuxeo.ecm.core.schema.SchemaManager;
052import org.nuxeo.ecm.core.schema.types.Field;
053import org.nuxeo.ecm.core.schema.types.Schema;
054import org.nuxeo.ecm.user.center.profile.UserProfileService;
055import org.nuxeo.runtime.services.config.ConfigurationService;
056
057/**
058 * @author <a href="mailto:ak@nuxeo.com">Arnaud Kervern</a>
059 * @since 8.1
060 */
061@Setup(mode = SINGLETON, priority = REFERENCE)
062public class UserProfileEnricher extends AbstractJsonEnricher<NuxeoPrincipal> {
063
064    public static final String NAME = "userprofile";
065
066    private static final FastDateFormat FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'");
067
068    /**
069     * @since 9.3
070     */
071    public static final String COMPATIBILITY_CONFIGURATION_PARAM = "nuxeo.userprofile.enricher.compatibility";
072
073    @Inject
074    protected SchemaManager schemaManager;
075
076    @Inject
077    protected UserProfileService userProfileService;
078
079    @Inject
080    protected ConfigurationService configurationService;
081
082    @Inject
083    protected DownloadService downloadService;
084
085    public UserProfileEnricher() {
086        super(NAME);
087    }
088
089    @Override
090    public void write(JsonGenerator jg, NuxeoPrincipal nuxeoPrincipal) throws IOException {
091        try (RenderingContext.SessionWrapper sw = ctx.getSession(null)) {
092            DocumentModel up = userProfileService.getUserProfileDocument(nuxeoPrincipal.getName(), sw.getSession());
093            jg.writeFieldName(NAME);
094            if (up == null) {
095                jg.writeNull();
096                return;
097            }
098
099            jg.writeStartObject();
100            if (configurationService.isBooleanPropertyTrue(COMPATIBILITY_CONFIGURATION_PARAM)) {
101                writeCompatibilityUserProfile(jg, up);
102            } else {
103                writeUserProfile(jg, up);
104            }
105            jg.writeEndObject();
106        }
107    }
108
109    protected void writeCompatibilityUserProfile(JsonGenerator jg, DocumentModel up) throws IOException {
110        Serializable propertyValue = up.getPropertyValue(USER_PROFILE_BIRTHDATE_FIELD);
111        jg.writeStringField("birthdate",
112                propertyValue == null ? null : FORMATTER.format(((GregorianCalendar) propertyValue).getTime()));
113        jg.writeStringField("phonenumber", (String) up.getPropertyValue(USER_PROFILE_PHONENUMBER_FIELD));
114        Blob avatar = (Blob) up.getPropertyValue(USER_PROFILE_AVATAR_FIELD);
115        if (avatar != null) {
116            String url = downloadService.getDownloadUrl(up, USER_PROFILE_AVATAR_FIELD, avatar.getFilename());
117            jg.writeStringField("avatar", ctx.getBaseUrl() + url);
118        } else {
119            jg.writeNullField("avatar");
120        }
121    }
122
123    protected void writeUserProfile(JsonGenerator jg, DocumentModel up) throws IOException {
124        Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, APPLICATION_JSON_TYPE);
125        Schema schema = schemaManager.getSchema(USER_PROFILE_SCHEMA);
126        // provides the user profile document to the property marshaller
127        try (Closeable resource = ctx.wrap().with(ENTITY_TYPE, up).open()) {
128            for (Field field : schema.getFields()) {
129                jg.writeFieldName(field.getName().getLocalName());
130                Property property = up.getProperty(field.getName().getPrefixedName());
131                OutputStream out = new OutputStreamWithJsonWriter(jg);
132                propertyWriter.write(property, Property.class, Property.class, APPLICATION_JSON_TYPE, out);
133            }
134        }
135    }
136}