/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.builder.entity.lookup;

// Java Classes

// Library Classes

// Framework Classes
import gov.va.med.fw.model.lookup.AbstractLookup;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.builder.AbstractBuilder;
import gov.va.med.fw.util.builder.BuilderException;

import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.UnknownLookupCodeException;

// Messaging Classes

/**
 * @author Martin Francisco
 */
public abstract class AbstractLookupBuilder
    extends AbstractBuilder
{
    private static final long serialVersionUID = -1370346746640850300L;
    private String defaultCode;
    private boolean defaultOnException = false;
    private boolean defaultOnNull = false;
    private LookupService lookupService;
    private Class lookupType;

    /**
     * Default contructor.
     */
    public AbstractLookupBuilder()
    {
        super();
    }

    public String getDefaultCode()
    {
        return this.defaultCode;
    }

    public void setDefaultCode(String defaultCode)
    {
        this.defaultCode = defaultCode;
    }

    public boolean isDefaultOnException()
    {
        return this.defaultOnException;
    }

    public void setDefaultOnException(boolean defaultOnException)
    {
        this.defaultOnException = defaultOnException;
    }

    public boolean isDefaultOnNull()
    {
        return this.defaultOnNull;
    }

    public void setDefaultOnNull(boolean defaultOnNull)
    {
        this.defaultOnNull = defaultOnNull;
    }

    public LookupService getLookupService()
    {
        return this.lookupService;
    }

    public void setLookupService(LookupService lookupService)
    {
        this.lookupService = lookupService;
    }

    public Class getLookupType()
    {
        return this.lookupType;
    }

    public void setLookupType(Class lookupType)
    {
        this.lookupType = lookupType;
    }

    public AbstractLookup build(String input) throws BuilderException
    {
        return (input == null) ? this.buildDefaultOnNull() : this
            .doBuild(input);
    }

    protected final AbstractLookup buildDefault() throws BuilderException
    {
        try
        {
            return (this.defaultCode == null) ? null : this
                .getByCodeInternal(this.defaultCode);
        }
        catch(ServiceException e)
        {
            throw new BuilderException(e.getMessage(), e);
        }
    }

    protected final AbstractLookup buildDefaultOnException(
        boolean shouldThrow,
        ServiceException e) throws BuilderException
    {
        if(this.defaultOnException)
        {
            return this.buildDefault();
        }
        else if(shouldThrow)
        {
            throw new BuilderException(e.getMessage(), e);
        }
        else
        {
            return null;
        }
    }

    protected final AbstractLookup buildDefaultOnNull() throws BuilderException
    {
        return this.defaultOnNull ? this.buildDefault() : null;
    }

    protected abstract AbstractLookup doBuild(String input)
        throws BuilderException;

    protected final AbstractLookup getByCode(String code)
        throws BuilderException
    {
        try
        {
            return (code == null) ? this.buildDefaultOnNull() : this
                .getByCodeInternal(code);
        }
        catch(UnknownLookupCodeException e)
        {
            return this.buildDefaultOnException(true, e);
        }
        catch(ServiceException e)
        {
            throw new BuilderException(e.getMessage(), e);
        }
    }

    private AbstractLookup getByCodeInternal(String code)
        throws ServiceException
    {
        return this.lookupService.getByCode(this.lookupType, code);
    }
}