//  Copyright 2004 The Apache Software Foundation
//
// 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.apache.tapestry.engine;

import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.tapestry.ApplicationRuntimeException;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IExternalPage;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.request.ResponseOutputStream;

/**
 * The external service enables external applications
 * to reference Tapestry pages via a URL. Pages which can be referenced
 * by the external service must implement the {@link IExternalPage}
 * interface. The external service enables the bookmarking of pages.
 * 
 * <p>
 * The external service may also be used by the Tapestry JSP taglibrary
 * ({@link org.apache.tapestry.jsp.ExternalURLTag} and {@link org.apache.tapestry.jsp.ExternalTag}).
 * 
 * <p> 
 * You can try and second guess the URL format used by Tapestry. 
 * The default URL format for the external service is:
 * <blockquote>
 * <tt>http://localhost/app?service=external/<i>[Page Name]</i>&amp;sp=[Param 0]&amp;sp=[Param 1]...</tt>
 * </blockquote>
 * For example to view the "ViewCustomer" page the service parameters 5056 (customer ID) and
 * 309 (company ID) the external service URL would be:
 * <blockquote>
 * <tt>http://localhost/myapp?service=external&amp;context=<b>ViewCustomer</b>&amp;sp=<b>5056</b>&amp;sp=<b>302</b></tt>
 * </blockquote>
 * In this example external service will get a "ViewCustomer" page and invoke the 
 * {@link IExternalPage#activateExternalPage(Object[], IRequestCycle)} method with the parameters:  
 * Object[] { new Integer(5056), new Integer(302) }.
 * <p>
 * Note service parameters (sp) need to be prefixed by valid
 * {@link org.apache.tapestry.util.io.DataSqueezer} adaptor char. These adaptor chars are automatically provided in
 * URL's created by the <tt>buildGesture()</tt> method. However if you hand coded an external 
 * service URL you will need to ensure valid prefix chars are present.
 * <p>
 * <table border="1" cellpadding="2">
 *  <tr>
 *   <th>Prefix char(s)</th><th>Mapped Java Type</th>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;TF</td><td>&nbsp;boolean</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;b</td><td>&nbsp;byte</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;c</td><td>&nbsp;char</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;d</td><td>&nbsp;double</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;-0123456789</td><td>&nbsp;integer</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;l</td><td>&nbsp;long</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;S</td><td>&nbsp;String</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;s</td><td>&nbsp;short</td>
 *  </tr>
 *  <tr>
 *   <td>&nbsp;other chars</td>
 *   <td>&nbsp;<tt>String</tt> without truncation of first char</td>
 *  </tr>
 * <table>
 *  <p>
 *  <p>
 *  A good rule of thumb is to keep the information encoded in the URL short and simple, and restrict it
 *  to just Strings and Integers.  Integers can be encoded as-is.  Prefixing all Strings with the letter 'S'
 *  will ensure that they are decoded properly.  Again, this is only relevant if an 
 *  {@link org.apache.tapestry.IExternalPage} is being referenced from static HTML or JSP and the
 *  URL must be assembled in user code ... when the URL is generated by Tapestry, it is automatically
 *  created with the correct prefixes and encodings (as with any other service).
 * 
 * @see org.apache.tapestry.IExternalPage
 * @see org.apache.tapestry.jsp.ExternalTag
 * @see org.apache.tapestry.jsp.ExternalURLTag
 *
 * @author Howard Lewis Ship
 * @author Malcolm Edgar
 * @since 2.2
 *  
 **/

public class ExternalService extends AbstractService
{

    public ILink getLink(IRequestCycle cycle, IComponent component, Object[] parameters)
    {
        if (parameters == null || parameters.length == 0)
            throw new ApplicationRuntimeException(
                Tapestry.format("service-requires-parameters", Tapestry.EXTERNAL_SERVICE));

        String pageName = (String) parameters[0];
        String[] context = new String[] { pageName };

        Object[] pageParameters = new Object[parameters.length - 1];
        System.arraycopy(parameters, 1, pageParameters, 0, parameters.length - 1);

        return constructLink(cycle, Tapestry.EXTERNAL_SERVICE, context, pageParameters, true);
    }

    public void service(
        IEngineServiceView engine,
        IRequestCycle cycle,
        ResponseOutputStream output)
        throws ServletException, IOException
    {
        IExternalPage page = null;

        String[] context = getServiceContext(cycle.getRequestContext());

        if (context == null || context.length != 1)
            throw new ApplicationRuntimeException(
                Tapestry.format("service-single-context-parameter", Tapestry.EXTERNAL_SERVICE));

        String pageName = context[0];

        try
        {
            page = (IExternalPage) cycle.getPage(pageName);
        }
        catch (ClassCastException ex)
        {
            throw new ApplicationRuntimeException(
                Tapestry.format("ExternalService.page-not-compatible", pageName),
                ex);
        }

        Object[] parameters = getParameters(cycle);

        cycle.setServiceParameters(parameters);

        cycle.activate(page);

        page.activateExternalPage(parameters, cycle);

        // Render the response.
        engine.renderResponse(cycle, output);
    }

    public String getName()
    {
        return Tapestry.EXTERNAL_SERVICE;
    }
}