/*
 * Copyright 2010 Google Inc.
 * 
 * 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.google.gwt.requestfactory.server;

import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
import com.google.gwt.requestfactory.shared.ServiceLocator;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.validation.ConstraintViolation;

/**
 * Users that intend to alter how RequestFactory interacts with the domain
 * environment can extend this type and provide it to
 * {@link ServiceLayer#create(ServiceLayerDecorator...)}. The methods defined in
 * this type will automatically delegate to the next decorator or the root
 * service object after being processed by{@code create()}.
 */
public class ServiceLayerDecorator extends ServiceLayer {
  private static final Logger log = Logger.getLogger(ServiceLayer.class.getName());

  /**
   * A pointer to the next deepest layer.
   */
  ServiceLayer next;

  @Override
  public <T> T createDomainObject(Class<T> clazz) {
    return getNext().createDomainObject(clazz);
  }

  @Override
  public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
    return getNext().createLocator(clazz);
  }

  @Override
  public Object createServiceInstance(Method contextMethod, Method domainMethod) {
    return getNext().createServiceInstance(contextMethod, domainMethod);
  }

  @Override
  public Object getId(Object domainObject) {
    return getNext().getId(domainObject);
  }

  @Override
  public Class<?> getIdType(Class<?> domainType) {
    return getNext().getIdType(domainType);
  }

  @Override
  public Object getProperty(Object domainObject, String property) {
    return getNext().getProperty(domainObject, property);
  }

  @Override
  public Type getRequestReturnType(Method contextMethod) {
    return getNext().getRequestReturnType(contextMethod);
  }

  @Override
  public Object getVersion(Object domainObject) {
    return getNext().getVersion(domainObject);
  }

  @Override
  public Object invoke(Method domainMethod, Object... args) {
    return getNext().invoke(domainMethod, args);
  }

  @Override
  public boolean isLive(Object domainObject) {
    return getNext().isLive(domainObject);
  }

  @Override
  public <T> T loadDomainObject(Class<T> clazz, Object domainId) {
    return getNext().loadDomainObject(clazz, domainId);
  }

  @Override
  public List<Object> loadDomainObjects(List<Class<?>> classes,
      List<Object> domainIds) {
    return getNext().loadDomainObjects(classes, domainIds);
  }

  @Override
  public boolean requiresServiceLocator(Method contextMethod,
      Method domainMethod) {
    return getNext().requiresServiceLocator(contextMethod, domainMethod);
  }

  @Override
  public Class<? extends BaseProxy> resolveClass(String typeToken) {
    return getNext().resolveClass(typeToken);
  }

  @Override
  public <T> Class<? extends T> resolveClientType(Class<?> domainClass,
      Class<T> clientType, boolean required) {
    return getNext().resolveClientType(domainClass, clientType, required);
  }

  @Override
  public Class<?> resolveDomainClass(Class<?> clazz) {
    return getNext().resolveDomainClass(clazz);
  }

  @Override
  public Method resolveDomainMethod(Method requestContextMethod) {
    return getNext().resolveDomainMethod(requestContextMethod);
  }

  @Override
  public Class<? extends Locator<?, ?>> resolveLocator(Class<?> domainType) {
    return getNext().resolveLocator(domainType);
  }

  @Override
  public Method resolveRequestContextMethod(String requestContextClass,
      String methodName) {
    return getNext().resolveRequestContextMethod(requestContextClass,
        methodName);
  }

  @Override
  public Class<? extends ServiceLocator> resolveServiceLocator(
      Method contextMethod, Method domainMethod) {
    return getNext().resolveServiceLocator(contextMethod, domainMethod);
  }

  @Override
  public String resolveTypeToken(Class<? extends BaseProxy> proxyType) {
    return getNext().resolveTypeToken(proxyType);
  }

  @Override
  public void setProperty(Object domainObject, String property,
      Class<?> expectedType, Object value) {
    getNext().setProperty(domainObject, property, expectedType, value);
  }

  @Override
  public <T> Set<ConstraintViolation<T>> validate(T domainObject) {
    return getNext().validate(domainObject);
  }

  /**
   * Throw a fatal error up into the top-level processing code. This method
   * should be used to provide diagnostic information that will help the
   * end-developer track down problems when that data would expose
   * implementation details of the server to the client.
   * 
   * @param e a throwable with more data, may be {@code null}
   * @param message a printf-style format string
   * @param args arguments for the message
   * @throws UnexpectedException this method never returns normally
   * @see #report(String, Object...)
   */
  protected final <T> T die(Throwable e, String message, Object... args)
      throws UnexpectedException {
    String msg = String.format(message, args);
    log.log(Level.SEVERE, msg, e);
    throw new UnexpectedException(msg, e);
  }

  /**
   * Returns the top-most service layer. General-purpose ServiceLayer decorators
   * should use the instance provided by {@code getTop()} when calling public
   * methods on the ServiceLayer API to allow higher-level decorators to
   * override behaviors built into lower-level decorators.
   * 
   * @return the ServiceLayer returned by
   *         {@link #create(ServiceLayerDecorator...)}
   */
  protected ServiceLayer getTop() {
    return top;
  }

  /**
   * Report an exception thrown by code that is under the control of the
   * end-developer.
   * 
   * @param an {@link InvocationTargetException} thrown by an invocation of
   *          user-provided code
   * @throws ReportableException this method never returns normally
   */
  protected final <T> T report(InvocationTargetException userGeneratedException)
      throws ReportableException {
    throw new ReportableException(userGeneratedException.getCause());
  }

  /**
   * Return a message to the client. This method should not include any data
   * that was not sent to the server by the client to avoid leaking data.
   * 
   * @param msg a printf-style format string
   * @param args arguments for the message
   * @throws ReportableException this method never returns normally
   * @see #die(Throwable, String, Object...)
   */
  protected final <T> T report(String msg, Object... args)
      throws ReportableException {
    throw new ReportableException(String.format(msg, args));
  }

  /**
   * Retrieves the next service layer. Used only by the server-package code and
   * accessed by used code via {@code super.doSomething()}.
   */
  final ServiceLayer getNext() {
    if (next == null) {
      // Unexpected, all methods should be implemented by some layer
      throw new UnsupportedOperationException();
    }
    return next;
  }
}
