/* * Copyright (C) 2011 Red Hat, Inc. and/or its affiliates. * * 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 org.jboss.errai.marshalling.client.marshallers; import org.jboss.errai.common.client.protocols.SerializationParts; import org.jboss.errai.common.client.util.Base64Util; import org.jboss.errai.marshalling.client.api.Marshaller; import org.jboss.errai.marshalling.client.api.MarshallingSession; import org.jboss.errai.marshalling.client.api.json.EJObject; import org.jboss.errai.marshalling.client.api.json.EJValue; /** * Used to wrap marshallers annotated with {@link org.jboss.errai.marshalling.client.api.annotations.AlwaysQualify} * * @author Mike Brock * @author Christian Sadilek <csadilek@redhat.com> */ public class QualifyingMarshallerWrapper<T> extends AbstractNullableMarshaller<T> { private final Marshaller<T> delegate; private final Class<T> type; public QualifyingMarshallerWrapper(final Marshaller<T> delegate, Class<T> type) { this.delegate = delegate; this.type = type; } @Override public T[] getEmptyArray() { return delegate.getEmptyArray(); } @Override public T doNotNullDemarshall(final EJValue o, final MarshallingSession ctx) { final EJObject obj = o.isObject(); if (obj != null) { final String objId = obj.get(SerializationParts.OBJECT_ID).isString().stringValue(); if (ctx.hasObject(objId)) { // noinspection unchecked return (T) ctx.getObject(Object.class, objId); } EJValue val = obj.get(SerializationParts.QUALIFIED_VALUE); if (val.isNull()) { val = o; } return ctx.recordObject(objId, delegate.demarshall(val, ctx)); } else { // This is to support one-dimensional Jackson char and byte array representations which cannot be wrapped in // an JSON object by the transfomer because they are indistinguishable from plain Strings. Class<?> componentType = type.getComponentType(); if (o.isString() != null && componentType != null) { if (componentType.equals(byte.class)) { return (T) Base64Util.decode(o.isString().stringValue()); } else if (componentType.equals(char.class)) { return (T) o.isString().stringValue().toCharArray(); } } } return null; } @Override public String doNotNullMarshall(final T o, final MarshallingSession ctx) { final boolean isNew = !ctx.hasObject(o); final StringBuilder buf = new StringBuilder("{\"").append(SerializationParts.ENCODED_TYPE).append("\":\"") .append(o.getClass().getName()).append("\",\"").append(SerializationParts.OBJECT_ID).append("\":\"") .append(ctx.getObject(o)).append("\""); if (!isNew) { return buf.append("}").toString(); } else { return buf.append(",\"").append(SerializationParts.QUALIFIED_VALUE).append("\":").append( delegate.marshall(o, ctx)) .append("}").toString(); } } }