com/aspc/cms/module/SiteScriptModule.java
/*
 *  Copyright (c) 2000-2004 ASP Converters pty ltd
 *
 *  www.aspconverters.com.au
 *
 *  All Rights Reserved.
 *
 *  This software is the proprietary information of
 *  ASP Converters Pty Ltd.
 *  Use is subject to license terms.
 */
package com.aspc.cms.module;

import javax.annotation.CheckReturnValue;
import com.aspc.remote.database.NotFoundException;
import com.aspc.DBObj.DBQuery;
import com.aspc.DBObj.MutableDataSource;
import com.aspc.DBObj.FldParams;
import com.aspc.DBObj.GlobalId;
import com.aspc.DBObj.DBClass;
import com.aspc.DBObj.DBField;
import com.aspc.DBObj.DBObject;
import com.aspc.DBObj.DBResult;
import com.aspc.DBObj.DataSource;
import com.aspc.DBObj.Errors.ValidationError;
import com.aspc.DBObj.Errors.ValidationList;
import com.aspc.DBObj.VirtualDB;
import com.aspc.remote.html.ClientBrowser;
import com.aspc.remote.util.misc.CLogger;
import com.supertracker.ScreenObj.SDBContext;
import com.supertracker.Servlets.WebClient;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import org.apache.commons.logging.Log;

/**
 *  <!--#ASPC_HEAD_START-->
 *
 *  The script module.
 *                                                                              <BR>
 *                                                                              <BR>
 *  <a href='doc-files/tree_sitescriptmodule.html' >data model</a><BR>
 *  <i>THREAD MODE: MIXED, SINGLE-THREADED when called from MutableDataSource else MULTI-THREADED</i>
 *  <!--#ASPC_HEAD_END--><BR>
 *
 *
 *  @author      Lei Gao
 *  @version     $Revision: 1.27 $
 *  @since       4 December 2003
 */
public class SiteScriptModule extends DBObject implements com.aspc.dal.cms.module.SiteScriptModule,com.aspc.style.BrowserFilter
{
    //#ASPC_GEN_START <editor-fold defaultstate="collapsed" desc="Automatically generated code (v2.5)">
    /** The script module */
    @SuppressWarnings("FieldNameHidesFieldInSuperclass")
    public static final String   DBCLASS_NAME="SiteScriptModule";

    /** The script module */
    public static final GlobalId DBCLASS_GID = GlobalId.cacheGlobalId("7700@1");

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue String getCode( final String... args)
    {
        return getFieldString( DBFIELD_CODE, args);
    }

    /** {@inheritDoc} */
    @Override
    public void setCode( final String value, final String... args) throws Exception
    {
        setValue( DBFIELD_CODE, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isBrowserChrome( final String... args)
    {
        return getBoolean( DBFIELD_BROWSER_CHROME, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setBrowserChrome( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_BROWSER_CHROME, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isBrowserFirefox( final String... args)
    {
        return getBoolean( DBFIELD_BROWSER_FIREFOX, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setBrowserFirefox( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_BROWSER_FIREFOX, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isBrowserIE( final String... args)
    {
        return getBoolean( DBFIELD_BROWSER_IE, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setBrowserIE( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_BROWSER_IE, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isBrowserOpera( final String... args)
    {
        return getBoolean( DBFIELD_BROWSER_OPERA, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setBrowserOpera( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_BROWSER_OPERA, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isBrowserSafari( final String... args)
    {
        return getBoolean( DBFIELD_BROWSER_SAFARI, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setBrowserSafari( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_BROWSER_SAFARI, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getChromeMaximumVersion( final String... args)
    {
        return getDouble( DBFIELD_CHROME_MAXIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setChromeMaximumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_CHROME_MAXIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getChromeMinimumVersion( final String... args)
    {
        return getDouble( DBFIELD_CHROME_MINIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setChromeMinimumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_CHROME_MINIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isDeprecated( final String... args)
    {
        return getBoolean( DBFIELD_DEPRECATED, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setDeprecated( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_DEPRECATED, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue String getDisplayFilter( final String... args)
    {
        return getFieldString( DBFIELD_DISPLAY_FILTER, args);
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getFirefoxMaximumVersion( final String... args)
    {
        return getDouble( DBFIELD_FIREFOX_MAXIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setFirefoxMaximumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_FIREFOX_MAXIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getFirefoxMinimumVersion( final String... args)
    {
        return getDouble( DBFIELD_FIREFOX_MINIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setFirefoxMinimumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_FIREFOX_MINIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isFormDesktop( final String... args)
    {
        return getBoolean( DBFIELD_FORM_DESKTOP, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setFormDesktop( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_FORM_DESKTOP, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isFormMobile( final String... args)
    {
        return getBoolean( DBFIELD_FORM_MOBILE, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setFormMobile( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_FORM_MOBILE, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue boolean isFormTablet( final String... args)
    {
        return getBoolean( DBFIELD_FORM_TABLET, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setFormTablet( final boolean value, final String... args) throws Exception
    {
        setValue( DBFIELD_FORM_TABLET, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getIeMaximumVersion( final String... args)
    {
        return getDouble( DBFIELD_IE_MAXIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setIeMaximumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_IE_MAXIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getIeMinimumVersion( final String... args)
    {
        return getDouble( DBFIELD_IE_MINIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setIeMinimumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_IE_MINIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue String getLabel( final String... args)
    {
        return getFieldString( DBFIELD_LABEL, args);
    }

    /** {@inheritDoc} */
    @Override
    public void setLabel( final String value, final String... args) throws Exception
    {
        setValue( DBFIELD_LABEL, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue @NotNull String getNotes( final String... args)
    {
        return getFieldString( DBFIELD_NOTES, args);
    }

    /** {@inheritDoc} */
    @Override
    public void setNotes( final String value, final String... args) throws Exception
    {
        setValue( DBFIELD_NOTES, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getOperaMaximumVersion( final String... args)
    {
        return getDouble( DBFIELD_OPERA_MAXIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setOperaMaximumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_OPERA_MAXIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getOperaMinimumVersion( final String... args)
    {
        return getDouble( DBFIELD_OPERA_MINIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setOperaMinimumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_OPERA_MINIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getSafariMaximumVersion( final String... args)
    {
        return getDouble( DBFIELD_SAFARI_MAXIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setSafariMaximumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_SAFARI_MAXIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public @CheckReturnValue double getSafariMinimumVersion( final String... args)
    {
        return getDouble( DBFIELD_SAFARI_MINIMUM_VERSION, FldParams.createIfNeeded(args));
    }

    /** {@inheritDoc} */
    @Override
    public void setSafariMinimumVersion( final double value, final String... args) throws Exception
    {
        setValue( DBFIELD_SAFARI_MINIMUM_VERSION, value, FldParams.createIfNeeded(args));
    }

    /**
     * Make a new instance of this class.
     * @param mds the datasource
     * @return the new record
     * @throws java.lang.Exception an object of this class could not be created
     */
    public static @CheckReturnValue SiteScriptModule create( @NotNull final MutableDataSource mds) throws Exception
    {
        return (SiteScriptModule)mds.create( DBCLASS_NAME);
    }

    /**
     * Make a new QUERY for this class.
     * @param ds the datasource
     * @return the new QUERY
     * @throws NotFoundException if class could not be found
     */
    public static @CheckReturnValue DBQuery<SiteScriptModule> makeQuery( @NotNull final DataSource ds) throws NotFoundException
    {
        return new DBQuery<>( DBCLASS_NAME, ds);
    }

    /**
     * Find the target for this class by the primary key
     * @param ds the datasource
     * @param key the value
     * @return the target
     * @throws NotFoundException if target could not be found
     * @throws java.lang.Exception a serious problem
     */
    public static @CheckReturnValue SiteScriptModule findKey( @NotNull final DataSource ds, final @NotNull String key) throws NotFoundException, Exception
    {
        DBQuery<SiteScriptModule>q= makeQuery( ds);
        q.addClause( DBFIELD_CODE,"=", key);
        return q.findOne();
    }
    //#ASPC_GEN_END </editor-fold>

    /**
     * Std. DBObject constructor
     *
     * @param def The class of this object
     * @param dataSource The datasource for this object
     * @throws Exception A serious problem occurred
     */
    public SiteScriptModule(final DBClass def, final DataSource dataSource) throws Exception
    {
        super( def, dataSource);
    }

    @Override
    /**
     * Additional validation for a particular field.
     *
     * @param list The validation list
     * @param field The field to be validated
     *
     * @throws Exception A serious problem
     *
     * @return The validation error
     */
    protected ValidationError extValidateField(DBField field, ValidationList list) throws Exception
    {
        String fn=field.getName();

        if( fn.equalsIgnoreCase(DBFIELD_CODE))
        {
            String code=getCode();
            final String pattern="[a-zA-Z0-9\\-_]+";
            if( code.matches(pattern)==false)
            {
                return list.createError(this, field, "Code: " + code + " must match pattern " + pattern);
            }
        }
        return super.extValidateField(field, list);
    }

    public static @NotNull String makeURI(@NotNull final SDBContext context, @NotNull final String code, final double maxVersion) throws Exception
    {
        VirtualDB layer = context.getDS().getDataBase();
        ClientBrowser browser=null;
        WebClient client = context.getClient();
        if( client != null)
        {
            browser = client.getBrowser();
        }
        return makeURI(layer, browser, code, maxVersion);
    }

    public static @NotNull String baseURI(@NotNull final SDBContext context, @NotNull final String code, final double maxVersion) throws Exception
    {
        VirtualDB layer = context.getDS().getDataBase();
        ClientBrowser browser=null;
        WebClient client = context.getClient();
        if( client != null)
        {
            browser = client.getBrowser();
        }
        return baseURI(layer, browser, code, maxVersion);
    }

    public static @NotNull String baseURI(
        @NotNull final WebClient client,
        @NotNull final String code,
        final double maxVersion
    ) throws Exception
    {
        VirtualDB layer = client.getDS().getDataBase();
        ClientBrowser browser=client.getBrowser();

        return baseURI(layer, browser, code, maxVersion);
    }

    public static @NotNull String makeURI(
        @NotNull final WebClient client,
        @NotNull final String code,
        final double maxVersion
    ) throws Exception
    {
        VirtualDB layer = client.getDS().getDataBase();
        ClientBrowser browser=client.getBrowser();

        return makeURI(layer, browser, code, maxVersion);
    }

    public static @NotNull String makeURI(@NotNull final VirtualDB layer, final ClientBrowser browser, @NotNull final String code, final double maxVersion) throws Exception
    {
        DBQuery<SiteScriptModule> ssmQ = SiteScriptModule.makeQuery(layer);
        ssmQ.addClause(SiteScriptModule.DBFIELD_CODE, "=", code);
        DBResult<SiteScriptModule> r = ssmQ.search();
        SiteScriptModule ssm = r.next();

        String scriptURI;
        if( ssm != null)
        {
            scriptURI = ssm.makeURI(browser, maxVersion);
        }
        else
        {
            throw new NotFoundException( "no module " + code);
        }

        if( r.hasMore())
        {
            LOGGER.warn( "duplicate moule code " + code);
        }
        return scriptURI;
    }

    public static @NotNull String baseURI(@NotNull final VirtualDB layer, final ClientBrowser browser, @NotNull final String code, final double maxVersion) throws Exception
    {
        DBQuery<SiteScriptModule> ssmQ = SiteScriptModule.makeQuery(layer);
        ssmQ.addClause(SiteScriptModule.DBFIELD_CODE, "=", code);
        DBResult<SiteScriptModule> r = ssmQ.search();
        SiteScriptModule ssm = r.next();

        String scriptURI;
        if( ssm != null)
        {
            scriptURI = ssm.baseURI(browser, maxVersion);
        }
        else
        {
            throw new NotFoundException( "no module " + code);
        }

        if( r.hasMore())
        {
            LOGGER.warn( "duplicate moule code " + code);
        }
        return scriptURI;
    }

    public @Nullable String makeURI( @NotNull final ClientBrowser browser, final double requiredMaxVersion) throws Exception
    {
        SiteScriptVersion ssv = getScriptVersion(browser, requiredMaxVersion);
        if(ssv != null)
        {
            return "/ds/" + ssv.getCode().toLowerCase();
        }

        return null;
    }

    /**
     * return the script version
     * @param browser
     * @param requiredMaxVersion
     * @return the value
     * @throws Exception a serious problem.
     */
    public SiteScriptVersion getScriptVersion( final ClientBrowser browser, final double requiredMaxVersion) throws Exception
    {
        DBQuery<SiteScriptVersion> q = SiteScriptVersion.makeQuery(ds.getDataBase());
        q.addClause(SiteScriptVersion.DBFIELD_MODULE, "IS", this);

        if( requiredMaxVersion>0)
        {
            q.addClause(SiteScriptVersion.DBFIELD_VERSION, "<=", requiredMaxVersion);
        }

        DBResult<SiteScriptVersion> r = q.search();
        r.setOrderBy( SiteScriptVersion.DBFIELD_VERSION, true);

        for( SiteScriptVersion ssv: r)
        {
            if( browser == null || ssv.doesMatch(browser))
            {
                return ssv;
            }
        }

        String msg="Could not find compatible version for the module: "+this.getCode() + " browser:" + browser;
        LOGGER.warn( msg);
        assert false: msg;

        r.rewind();
        return r.next();
    }

    public String baseURI( final ClientBrowser browser, final double requiredMaxVersion) throws Exception
    {
        SiteScriptVersion ssv = getScriptVersion(browser, requiredMaxVersion);
        if(ssv != null)
        {
            String path=ssv.getCode().toLowerCase();
            int pos = path.lastIndexOf("/");
            return "/ds/" + path.substring(0, pos + 1);
        }
        return null;
    }

    private static final Log LOGGER = CLogger.getLog( "com.aspc.cms.module.SiteScriptModule");//#LOGGER-NOPMD
}