CVS: TapestryBook/examples/src/java/examples/cc CreditCardResults.java,NONE,1.1 CreditCardStrings.properties,NONE,1.1 CreditCard.java,NONE,1.1 CreditCardType.java,NONE,1.1 CreditCardField.java,NONE,1.1

Howard Lewis Ship <[email protected]> Fri, 11 Jul 2003 21:16:46 -0700
Newsgroups gmane.comp.java.tapestry.cvs
Message-ID <[email protected]>
Update of /cvsroot/tapestry/TapestryBook/examples/src/java/examples/cc
In directory sc8-pr-cvs1:/tmp/cvs-serv6871/examples/src/java/examples/cc

Added Files:
	CreditCardResults.java CreditCardStrings.properties 
	CreditCard.java CreditCardType.java CreditCardField.java 
Log Message:
Reorganize examples application to reflect standard organization

--- NEW FILE: CreditCardResults.java ---
package examples.cc;

import org.apache.tapestry.html.BasePage;

public abstract class CreditCardResults extends BasePage
{
    public abstract void setCardNumber(String cardNumber);
    public abstract void setCardType(CreditCardType type);
}

--- NEW FILE: CreditCardStrings.properties ---
# $Id: CreditCardStrings.properties,v 1.1 2003/07/12 04:16:44 hship Exp $

MASTERCARD=Master Card
VISA=Visa

--- NEW FILE: CreditCard.java ---
package examples.cc;

import java.util.ResourceBundle;

import org.apache.commons.lang.enum.Enum;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.form.EnumPropertySelectionModel;
import org.apache.tapestry.form.IPropertySelectionModel;
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.valid.IValidationDelegate;

public abstract class CreditCard extends BasePage
{
    private IPropertySelectionModel _cardModel;

    public abstract String getCardNumber();
    public abstract CreditCardType getCardType();

    public IPropertySelectionModel getCardModel()
    {
        if (_cardModel == null)
        {
            _cardModel =
                new EnumPropertySelectionModel(
                    new Enum[] { CreditCardType.MASTERCARD, CreditCardType.VISA },
                    ResourceBundle.getBundle("examples.cc.CreditCardStrings", getLocale()));
        }

        return _cardModel;
    }

    public void formSubmit(IRequestCycle cycle)
    {
        IValidationDelegate delegate = (IValidationDelegate) getBeans().getBean("delegate");

        if (delegate.getHasErrors())
            return;

        CreditCardResults results = (CreditCardResults) cycle.getPage("CreditCardResults");
        results.setCardNumber(getCardNumber());
        results.setCardType(getCardType());

        cycle.activate(results);
    }
}

--- NEW FILE: CreditCardType.java ---
package examples.cc;

import org.apache.commons.lang.enum.Enum;


public class CreditCardType extends Enum
{
	public static final CreditCardType MASTERCARD = new CreditCardType("MASTERCARD");
	public static final CreditCardType VISA = new CreditCardType("VISA");

    public CreditCardType(String name)
    {
        super(name);
    }

}

--- NEW FILE: CreditCardField.java ---
package examples.cc;

import java.util.HashMap;
import java.util.Map;

import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.tapestry.ApplicationRuntimeException;
import org.apache.tapestry.IForm;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceLocation;
import org.apache.tapestry.IScript;
import org.apache.tapestry.engine.IScriptSource;
import org.apache.tapestry.form.AbstractFormComponent;
import org.apache.tapestry.form.FormEventType;
import org.apache.tapestry.html.Body;
import org.apache.tapestry.request.RequestContext;
import org.apache.tapestry.valid.IValidationDelegate;
import org.apache.tapestry.valid.ValidationConstraint;
import org.apache.tapestry.valid.ValidatorException;

/**
 * Renders as a set of four input fields for entering
 * a common credit-card number.
 *
 * @author Howard Lewis Ship
 * @version $Id: CreditCardField.java,v 1.1 2003/07/12 04:16:44 hship Exp $
 */
public abstract class CreditCardField extends AbstractFormComponent
{
    private IScript _script;
    private Pattern _compiledPattern;
    private Perl5Matcher _matcher;

    public abstract void setCardNumber(String cardNumber);
    public abstract String getCardNumber();

    protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
    {
        IForm form = getForm(cycle);

        // Get the base name; we extend this to create four seperate query parameters.

        String name = form.getElementId(this);
        boolean disabled = isDisabled();
        IValidationDelegate delegate = form.getDelegate();

        if (form.isRewinding())
        {
            if (!disabled)
                updateCardNumberFromRequest(name, form, delegate, cycle);

            return;
        }

        // If the page is rewinding, but the form isn't,
        // then no point in doing anything else.

        if (cycle.isRewinding())
            return;

        String cardNumber[] = extractCardNumber(delegate);

		delegate.writePrefix(writer, cycle, this, null);
		
        for (int i = 0; i < 4; i++)
        {
            if (i > 0)
                writer.print(" - ");

            // $ is a good separator because its not allowed as a normal component id,
            // so there's no chance of conflict.

            String fieldName = name + "$g" + i;

            writer.beginEmpty("input");
            writer.attribute("type", "text");
            writer.attribute("name", fieldName);
            writer.attribute("size", 4);
            writer.attribute("maxlength", 4);
            writer.attribute("value", cardNumber[i]);

            if (disabled)
                writer.attribute("disabled", "disabled");

            // The delegate updates *each* of the rendered text fields.

            delegate.writeAttributes(writer, cycle, this, null);
        }
		
		delegate.writeSuffix(writer, cycle, this, null);
		
        if (!disabled)
        {
            // Now run the script.

            if (_script == null)
            {
                IScriptSource source = cycle.getEngine().getScriptSource();
                IResourceLocation specLocation =
                    getSpecification().getLocation().getResourceLocation();
                IResourceLocation scriptLocation =
                    specLocation.getRelativeLocation("CreditCardField.script");

                _script = source.getScript(scriptLocation);
            }

			Body body = Body.get(cycle);

            Map symbols = new HashMap();
            symbols.put("creditCardField", this);
            symbols.put("formatMessage", getMessage("card-number-format"));

            _script.execute(cycle, body, symbols);

            String formValidateFunction = (String) symbols.get("formValidateFunction");

            form.addEventHandler(FormEventType.SUBMIT, formValidateFunction);
        }
    }

    private void updateCardNumberFromRequest(
        String name,
        IForm form,
        IValidationDelegate delegate,
        IRequestCycle cycle)
    {
        RequestContext context = cycle.getRequestContext();

        StringBuffer buffer = new StringBuffer();

        for (int i = 0; i < 4; i++)
        {
            String value = context.getParameter(name + "$g" + i);

            if (value != null)
            {
                // This shouldn't happen because we set a maxlength
                // for the fields.

                if (value.length() > 4)
                    value = value.substring(0, 4);

                buffer.append(value);
            }

            // This shouldn't happen, because the client-side
            // script checks that each field has exactly
            // the right number of digits.

            while (buffer.length() < 4 * (i + 1))
                buffer.append(' ');
        }

        String cardNumber = buffer.toString();

        delegate.recordFieldInputValue(cardNumber);

        try
        {
            validate(cardNumber);
            setCardNumber(cardNumber);
        }
        catch (ValidatorException ex)
        {
            delegate.record(ex);
        }

    }

    private String[] extractCardNumber(IValidationDelegate delegate)
    {
        String cardNumber = delegate.getFieldInputValue();

        if (cardNumber == null)
            cardNumber = getCardNumber();

        if (cardNumber == null)
            return new String[] { "", "", "", "" };

        String[] result = new String[4];
        StringBuffer buffer = new StringBuffer(cardNumber);

        while (buffer.length() < 16)
            buffer.append(' ');

        for (int i = 0; i < 4; i++)
            result[i] = buffer.substring(4 * i, 4 * (i + 1));

        return result;
    }

    private void validate(String cardNumber) throws ValidatorException
    {
        if (_compiledPattern == null)
        {
            Perl5Compiler compiler = new Perl5Compiler();
            try
            {
                _compiledPattern = compiler.compile("^\\d{16}$");
            }
            catch (MalformedPatternException ex)
            {
                throw new ApplicationRuntimeException(ex);
            }
        }

        if (_matcher == null)
            _matcher = new Perl5Matcher();

        if (_matcher.matches(cardNumber, _compiledPattern))
            return;

        String formatted =
            cardNumber.substring(0, 4)
                + "-"
                + cardNumber.substring(4, 8)
                + "-"
                + cardNumber.substring(8, 12)
                + "-"
                + cardNumber.substring(12);

        throw new ValidatorException(
            format("invalid-card-number", formatted),
            ValidationConstraint.NUMBER_FORMAT);
    }
}



-------------------------------------------------------
This SF.Net email sponsored by: Parasoft
Error proof Web apps, automate testing & more.
Download & eval WebKing and get a free book.
www.parasoft.com/bulletproofapps1