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