All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.geeoz.ean.ws.rs.JsonFormBodyWriter Maven / Gradle / Ivy

/*
 * Copyright 2013 Geeoz Software
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.geeoz.ean.ws.rs;

import com.ean.wsapi.hotel.v3.BaseRequest;
import com.ean.wsapi.hotel.v3.LocaleType;
import com.ean.wsapi.hotel.v3.Room;
import com.ean.wsapi.hotel.v3.RoomGroup;
import org.glassfish.jersey.message.internal.ReaderWriter;

import javax.security.auth.Subject;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.security.PrivilegedAction;
import java.util.List;

/**
 * Provider for marshalling of {@code application/x-www-form-urlencoded}
 * entity type from {@link BaseRequest} child instance.
 *
 * @author Alex Voloshyn
 * @version 1.0 7/13/2013
 */
@Provider
@Produces("application/x-www-form-urlencoded")
public final class JsonFormBodyWriter
        implements MessageBodyWriter {
    /**
     * UTF-8 charset name.
     */
    private static final String CHARSET_NAME = "UTF-8";

    /**
     * Write a type to an string builder.
     *
     * @param type    the instance to write
     * @param object  the instance to write
     * @param builder string builder
     */
    public static void writeTo(final Class type,
                               final Object object,
                               final StringBuilder builder) {
        final Class superclass = type.getSuperclass();
        if (superclass != null) {
            writeTo(superclass, object, builder);
        }
        Subject.doAsPrivileged(null, new PrivilegedAction() {
            @Override
            public Object run() {
                for (Field field : type.getDeclaredFields()) {
                    field.setAccessible(true);
                    try {
                        final Object value = field.get(object);
                        if (value != null) {
                            writeTo(field.getName(), value, builder);
                        }
                    } catch (IllegalAccessException iae) {
                        iae.printStackTrace();
                    }
                }
                return null;
            }
        }, null);
    }

    /**
     * Write a object to an string builder.
     *
     * @param name    name
     * @param object  object value
     * @param builder string builder
     */
    public static void writeTo(final String name,
                               final Object object,
                               final StringBuilder builder) {
        if (object instanceof List) {
            writeList(name, (List) object, builder);
        } else if (object instanceof LocaleType) {
            writeLocaleType(name, (LocaleType) object, builder);
        } else if (object instanceof RoomGroup) {
            writeRoomGroup((RoomGroup) object, builder);
        } else {
            writeString(name, String.valueOf(object), builder);
        }
    }

    /**
     * Write a string to an string builder.
     *
     * @param name    name
     * @param string  string value
     * @param builder string builder
     */
    private static void writeString(final String name,
                                    final String string,
                                    final StringBuilder builder) {
        try {
            builder.append('&');
            builder.append(URLEncoder.encode(name, CHARSET_NAME));
            builder.append('=');
            builder.append(URLEncoder.encode(string, CHARSET_NAME));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * Write a list to an string builder.
     *
     * @param name    name
     * @param list    list value
     * @param builder string builder
     */
    private static void writeList(final String name,
                                  final List list,
                                  final StringBuilder builder) {
        try {
            builder.append('&');
            builder.append(URLEncoder.encode(name, CHARSET_NAME));
            builder.append('=');
            for (Object value : list) {
                builder.append(URLEncoder.encode(
                        String.valueOf(value), CHARSET_NAME));
                builder.append(',');
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * Write a string to an string builder.
     *
     * @param name    name
     * @param locale  locale value
     * @param builder string builder
     */
    private static void writeLocaleType(final String name,
                                        final LocaleType locale,
                                        final StringBuilder builder) {
        try {
            builder.append('&');
            builder.append(URLEncoder.encode(name, CHARSET_NAME));
            builder.append('=');
            builder.append(URLEncoder.encode(locale.value(), CHARSET_NAME));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * Write a string to an string builder.
     *
     * @param group   room group
     * @param builder string builder
     */
    private static void writeRoomGroup(final RoomGroup group,
                                       final StringBuilder builder) {
        try {
            int index = 1;
            for (Room room : group.getRoom()) {
                builder.append('&');
                builder.append(URLEncoder.encode("room", CHARSET_NAME));
                builder.append(index);
                builder.append('=');
                builder.append(room.getNumberOfAdults());
                for (int child : room.getChildAges()) {
                    builder.append(',');
                    builder.append(child);
                }
                index++;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean isWriteable(final Class type,
                               final Type genericType,
                               final Annotation[] annotations,
                               final MediaType mediaType) {
        return BaseRequest.class.isAssignableFrom(type);
    }

    @Override
    public long getSize(final BaseRequest request,
                        final Class type,
                        final Type genericType,
                        final Annotation[] annotations,
                        final MediaType mediaType) {
        /* In general figuring output size requires actual writing; usually not
         * worth it to write everything twice.
         */
        return -1;
    }

    @Override
    public void writeTo(final BaseRequest request,
                        final Class type,
                        final Type genericType,
                        final Annotation[] annotations,
                        final MediaType mediaType,
                        final MultivaluedMap headers,
                        final OutputStream entityStream)
            throws IOException {
        final StringBuilder builder = new StringBuilder();
        writeTo(request.getClass(), request, builder);
        ReaderWriter.writeToAsString(
                builder.toString(), entityStream, mediaType);
    }
}