Package br.com.caelum.restfulie.mediatype

Source Code of br.com.caelum.restfulie.mediatype.XStreamHelper$LinkSupportWrapper

package br.com.caelum.restfulie.mediatype;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import br.com.caelum.restfulie.Resource;
import br.com.caelum.restfulie.http.DefaultRelation;
import br.com.caelum.restfulie.relation.Enhancer;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.ReflectionProviderWrapper;
import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.mapper.MapperWrapper;

@SuppressWarnings("unchecked")
public class XStreamHelper {

  private final class EnhancedLookupProvider extends
      ReflectionProviderWrapper {
    private EnhancedLookupProvider(ReflectionProvider wrapper) {
      super(wrapper);
    }

    @Override
    public Object newInstance(Class originalType) {
      if (realTypes.containsKey(originalType)) {
        return super.newInstance(realTypes.get(originalType));
      } else if (!Modifier.isFinal(originalType.getModifiers())) {
        // enhance now!
        Class enhanced = new Enhancer().enhanceResource(originalType);
        return super.newInstance(enhanced);
      }
      return super.newInstance(originalType);
    }
  }

  @SuppressWarnings("deprecation")
  private class LinkSupportWrapper extends MapperWrapper {

    public LinkSupportWrapper(Mapper wrapped) {
      super(wrapped);
    }

    @Override
    public String getFieldNameForItemTypeAndName(Class definedIn,
        Class itemType, String itemFieldName) {
      if (realTypes.containsKey(definedIn)
          && itemFieldName.equals("link")) {
        return "link";
      }
      return super.getFieldNameForItemTypeAndName(definedIn, itemType,
          itemFieldName);
    }

    @Override
    public String serializedClass(Class type) {
      if (Resource.class.isAssignableFrom(type)) {
        return super.serializedClass(type.getSuperclass());
      }
      return super.serializedClass(type);
    }

    @Override
    public boolean shouldSerializeMember(Class definedIn, String fieldName) {
      if (Resource.class.isAssignableFrom(definedIn) && fieldName.equals("link")) {
        return false;
      }
      return super.shouldSerializeMember(definedIn, fieldName);
    }

  }

  private final HierarchicalStreamDriver driver;

  private final Map<Class, Class> realTypes = new HashMap<Class, Class>();

  public XStreamHelper(HierarchicalStreamDriver driver) {
    this.driver = driver;
  }

  /**
   * Extension point to define your own provider.
   *
   * @return
   */
  private ReflectionProvider getProvider() {
    return new EnhancedLookupProvider(new Sun14ReflectionProvider());
  }

  /**
   * Extension point for configuring your xstream instance.
   *
   * @param typesToEnhance
   * @param list
   * @return an xstream instance with support for link enhancement.
   */
  public XStream getXStream(List<Class> typesToEnhance, List<String> collectionNames) {
    ReflectionProvider provider = getProvider();

    XStream xstream = new XStream(provider, driver) {
      @Override
      protected MapperWrapper wrapMapper(MapperWrapper next) {
        return new LinkSupportWrapper(next);
      }

    };
    xstream.useAttributeFor(DefaultRelation.class, "rel");
    xstream.useAttributeFor(DefaultRelation.class, "href");
    xstream.useAttributeFor(DefaultRelation.class, "type");

    for (Class type : typesToEnhance) {
      realTypes.put(type, new Enhancer().enhanceResource(type));
      xstream.processAnnotations(type);
    }

    Class enhancedType = new Enhancer().enhanceResource(EnhancedList.class);
    realTypes.put(EnhancedList.class, enhancedType);

    for (String name : collectionNames) {
      xstream.alias(name, enhancedType);
    }

    for (Class type : typesToEnhance) {
      xstream.addImplicitCollection(enhancedType, "elements", xstream.getMapper().serializedClass(type), type);
    }

    for (Class customType : realTypes.values()) {
      xstream.addImplicitCollection(customType, "link", "link", DefaultRelation.class);
    }

    return xstream;
  }

}
TOP

Related Classes of br.com.caelum.restfulie.mediatype.XStreamHelper$LinkSupportWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.