Package com.scooterframework.web.route

Source Code of com.scooterframework.web.route.Resource

/*
*   This software is distributed under the terms of the FSF
*   Gnu Lesser General Public License (see lgpl.txt).
*
*   This program is distributed WITHOUT ANY WARRANTY. See the
*   GNU General Public License for more details.
*/
package com.scooterframework.web.route;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.scooterframework.common.logging.LogUtil;
import com.scooterframework.common.util.Converters;
import com.scooterframework.common.util.PropertyFileUtil;
import com.scooterframework.common.util.StringUtil;
import com.scooterframework.common.util.WordUtil;
import com.scooterframework.orm.sqldataexpress.config.DatabaseConfig;
import com.scooterframework.orm.sqldataexpress.object.PrimaryKey;
import com.scooterframework.orm.sqldataexpress.util.SqlExpressUtil;

/**
* Resource class
*
* @author (Fei) John Chen
*/
public class Resource {
    private LogUtil log = LogUtil.getLogger(this.getClass().getName());

    /**
     * Constant which indicates that this is a plural resource.
     */
    public static final int PLURAL = 0;

    /**
     * Constant which indicates that this is a single resource.
     */
    public static final int SINGLE = 1;

    private static String[] standardRestfulActionNames =
                                {RouteConstants.ROUTE_ACTION_LIST_RESOURCES,
                                 RouteConstants.ROUTE_ACTION_ADD_RESOURCE,
                                 RouteConstants.ROUTE_ACTION_CREATE_RESOURCE,
                                 RouteConstants.ROUTE_ACTION_READ_RESOURCE,
                                 RouteConstants.ROUTE_ACTION_EDIT_RESOURCE,
                                 RouteConstants.ROUTE_ACTION_UPDATE_RESOURCE,
                                 RouteConstants.ROUTE_ACTION_DELETE_RESOURCE};

  protected String name;
    protected int type;
  protected String controller;
  protected String controllerClass;
  protected String singular;
  protected String namespace;
  protected String pathPrefix;
  protected String pathAlias;
  protected String actionAlias;
  protected String only;
  protected String except;
  protected String member;
  protected String collection;
  protected String add;
    protected String requirements;
    protected String parents;

    private String model;
    private String connName;
    private String implicitPathPrefix;
    private boolean strictParent = false;
    private boolean autoRoute;

  private Properties actionAliasProperties;
    private List<RestRoute> routes = new ArrayList<RestRoute>();

    /**
     * Creates a resource instance of either single or plural type.
     *
   * @param name Name of the resource
   * @param type Either SINGLE or PLURAL
     */
  public Resource(String name, int type) {
    this(name, type, new Properties());
  }

  /**
   * Creates a resource instance, but uses <tt>noRoute</tt> parameter to
   * indicate if routes of the resource are allowed to be created.
   *
   * @param name     Name of the resource
   * @param noRoutes True if no routes are allowed to create
   */
  public Resource(String name, boolean noRoutes) {
    this(name, PLURAL, new Properties(), noRoutes, false);
  }

  /**
   * Creates a resource instance of either single or plural type with a
   * specific property <tt>p</tt>.
   *
   * @param name Name of the resource
   * @param type Either SINGLE or PLURAL
   * @param p    properties of the resource
   */
  public Resource(String name, int type, Properties p) {
        this(name, type, p, false, false);
  }

  Resource(String name, int type, Properties p, boolean noRoutes, boolean autoRoute) {
    this.name = name;
    this.type = type;
        this.autoRoute = autoRoute;

        if (name == null || "".equals(name))
            throw new IllegalArgumentException("Name cannot be null or empty " +
            "when instantiating a Resource.");

        if (type != SINGLE && type != PLURAL)
            throw new IllegalArgumentException("Invalid resource type \"" + type +
                    "\". Only \"" + PLURAL + "\" (plural) and \"" + SINGLE +
                    "\" (single) are allowed.");

    populateProperties(p);

        if (type == SINGLE) {
            if (except == null ||
                except.indexOf(RouteConstants.ROUTE_ACTION_LIST_RESOURCES) == -1) {
                except += " " + RouteConstants.ROUTE_ACTION_LIST_RESOURCES;
            }
        }

        if (!noRoutes) createRoutes();
  }

  public String getName() {
    return name;
  }

  public int getType() {
    return type;
  }

    public boolean isSingle() {
        return (SINGLE == type);
    }

  public String getController() {
    return (controller != null)?controller:name;
  }

  public String getControllerClass() {
    return controllerClass;
  }

  public String getSingular() {
    return singular;
  }

  public String getNamespace() {
    return namespace;
  }

  public String getPathPrefix() {
    return pathPrefix;
  }

  public String getPathAlias() {
    return pathAlias;
  }

    //Note: It is important that the returned url must be prefixed with a
    //slash, because other code depend on it.
    public String getUnprifixedURL() {
        return "/" + ((pathAlias != null)?pathAlias:name);
    }

    public String getScreenURLPattern() {
        String url = getUnprifixedURL();
        if (pathPrefix != null) {
            url = pathPrefix + url;
        }
        else {
            if (implicitPathPrefix != null) {
                url = implicitPathPrefix + url;
            }
        }
        return url;
    }

    /**
     * Returns url string.
     *
     * @param fieldValues   name/value pairs to be used to resolve dynamic url.
     * @return a url
     */
    public String getScreenURL(Map<String, String> fieldValues) {
        return Route.resolveURL(getScreenURLPattern(), fieldValues);
    }

  public String getActionAlias() {
    return actionAlias;
  }

  public String getOnly() {
    return only;
  }

  public String getExcept() {
    return except;
  }

  public String getMember() {
    return member;
  }

  public String getCollection() {
    return collection;
  }

  public String getAdd() {
    return add;
  }

  public String getRequirements() {
    return requirements;
  }

    public String getParents() {
        return parents;
    }

    public boolean isStrictParent() {
        return strictParent;
    }

    public String getModel() {
        return model;
    }

    public List<RestRoute> getRoutes() {
        return routes;
    }

    /**
     * Returns a rest route of the underlying resource. The <tt>target</tt>
     * must a model name if a member route is desired, or a resource name if a
     * collection route is wanted.
     *
     * @param action     action name
     * @param target     target name
     * @return resource
     */
    public RestRoute getRestRoute(String action, String target) {
        RestRoute rr = null;
        String routeName = createRestRouteName(action, target);
        Iterator<RestRoute> it = routes.iterator();
        while(it.hasNext()) {
            RestRoute tmp = it.next();
            if (tmp.getName().equals(routeName)) {
                rr = tmp;
                break;
            }
        }
        return rr;
    }

  /**
     * Returns a string representation of the object.
     * @return String
     */
    public String toString() {
        StringBuilder returnString = new StringBuilder();
        String SEPARATOR = ", ";

        returnString.append("name = " + name).append(SEPARATOR);
        returnString.append("type = " + type).append(SEPARATOR);
        returnString.append("controller = " + controller).append(SEPARATOR);
        returnString.append("controllerClass = " + controllerClass).append(SEPARATOR);
        returnString.append("singular = " + singular).append(SEPARATOR);
        returnString.append("namespace = " + namespace).append(SEPARATOR);
        returnString.append("pathPrefix = " + pathPrefix).append(SEPARATOR);
        returnString.append("pathAlias = " + pathAlias).append(SEPARATOR);
        returnString.append("actionAlias = " + actionAlias).append(SEPARATOR);
        returnString.append("only = " + only).append(SEPARATOR);
        returnString.append("except = " + except).append(SEPARATOR);
        returnString.append("member = " + member).append(SEPARATOR);
        returnString.append("collection = " + collection).append(SEPARATOR);
        returnString.append("add = " + add).append(SEPARATOR);
        returnString.append("requirements = " + requirements).append(SEPARATOR);
        returnString.append("parents = " + parents).append(SEPARATOR);
        returnString.append("strictParent = " + strictParent).append(SEPARATOR);
        returnString.append("implicitPathPrefix = " + implicitPathPrefix).append(SEPARATOR);
        returnString.append("model = " + model);

        return returnString.toString();
    }

    /**
     * Returns a format string for resource id. For example, for a resource
     * named "<tt>users</tt>", the resource id is "<tt>user_id</tt>";
     *
     * @param resource a resource
     * @return a format string for resource id
     */
    public static String getNesteeIdFormat(Resource resource) {
        return resource.getModel() + "_id";
    }

  protected void populateProperties(Properties p) {
    controller = p.getProperty(RouteConstants.ROUTE_KEY_CONTROLLER);
    controllerClass = p.getProperty(RouteConstants.ROUTE_KEY_CONTROLLER_CLASS);
    singular = p.getProperty(RouteConstants.ROUTE_KEY_SINGULAR);
    namespace = p.getProperty(RouteConstants.ROUTE_KEY_NAMESPACE);
    pathPrefix = p.getProperty(RouteConstants.ROUTE_KEY_PATH_PREFIX);
    pathAlias = p.getProperty(RouteConstants.ROUTE_KEY_PATH_ALIAS);

    actionAlias = p.getProperty(RouteConstants.ROUTE_KEY_ACTION_ALIAS);
        actionAlias = StringUtil.remove(actionAlias, RouteConstants.PROPERTY_SYMBOL_GROUP);

    if (actionAlias != null) {
      actionAliasProperties =
                Converters.convertStringToProperties(actionAlias,
                        RouteConstants.PROPERTY_SYMBOL_GROUP_ITEM_ASSIGN,
                        RouteConstants.PROPERTY_SYMBOL_GROUP_ITEMS_DELIMITER);
    }

    only = p.getProperty(RouteConstants.ROUTE_KEY_ONLY);
        only = StringUtil.remove(only, RouteConstants.PROPERTY_SYMBOL_ARRAY);

    except = p.getProperty(RouteConstants.ROUTE_KEY_EXCEPT);
        except = StringUtil.remove(except, RouteConstants.PROPERTY_SYMBOL_ARRAY);

        member = p.getProperty(RouteConstants.ROUTE_KEY_MEMBER);
        member = StringUtil.remove(member, RouteConstants.PROPERTY_SYMBOL_GROUP);

        collection = p.getProperty(RouteConstants.ROUTE_KEY_COLLECTION);
        collection = StringUtil.remove(collection, RouteConstants.PROPERTY_SYMBOL_GROUP);

        add = p.getProperty(RouteConstants.ROUTE_KEY_ADD);
        add = StringUtil.remove(add, RouteConstants.PROPERTY_SYMBOL_GROUP);

        requirements = p.getProperty(RouteConstants.ROUTE_KEY_REQUIREMENTS);

    parents = p.getProperty(RouteConstants.ROUTE_KEY_PARENTS);
        parents = StringUtil.remove(parents, RouteConstants.PROPERTY_SYMBOL_ARRAY);
        if (parents != null && parents.indexOf(RouteConstants.PROPERTY_SYMBOL_STRICT_PARENT) != -1) {
            if (!parents.startsWith(RouteConstants.PROPERTY_SYMBOL_STRICT_PARENT)) {
                throw new IllegalArgumentException("Resource definition error for \"" +
                        getName() + "\": " + RouteConstants.PROPERTY_SYMBOL_STRICT_PARENT +
                        " must be the first word for parents key.");
            }
            else {
                parents = parents.substring(RouteConstants.PROPERTY_SYMBOL_STRICT_PARENT.length()).trim();
                strictParent = true;
            }
        }

        //populate derived fields
        if (singular != null) {
            model = singular;
        }
        else {
            model = (DatabaseConfig.getInstance().usePluralTableName())?WordUtil.singularize(name):name;
        }
  }

    protected void createRoutes() {
        //
        //parse allowed actions
        //
        String[] allowedActionNames = standardRestfulActionNames;
        if (only != null) {
            allowedActionNames = Converters.convertStringToStringArray(only, RouteConstants.PROPERTY_SYMBOL_ARRAY_ITEMS_DELIMITER);
        }
        else if (except != null) {
            allowedActionNames = updateActionNamesByExcept(except);
        }

        if (allowedActionNames == null || allowedActionNames.length ==0) return;

        //
        //Start to create all kinds of routes
        //

        //
        //create nested routes
        //
        if (parents != null) {
            String[] parentsArray = Converters.convertStringToStringArray(parents,
                            RouteConstants.PROPERTY_SYMBOL_ARRAY_ITEMS_DELIMITER);
            if (parentsArray != null && parentsArray.length > 0) {
                //create all 7 restful nested routes in another method.
                int total = parentsArray.length;

                if (isStrictParent() && total > 1) {
                    throw new IllegalArgumentException("Resource definition error for \"" +
                        getName() + "\": There can be only one parent in strict case.");
                }

                String nestedPrefix = "";

                for (int j = 0; j < total; j++) {
                    String[] parentResourceNames = Converters.convertStringToStringArray(parentsArray[j], RouteConstants.PROPERTY_SYMBOL_PARENTS_CONNECTION);
                    Resource[] parentResource = getParentResource(parentResourceNames);
                    nestedPrefix = getNestedURLPrefixString(parentResource);
                    String indexURLNested = getNestedURLStringForList(nestedPrefix);
                    String  curdURLNested = getNestedURLStringForCRUD(nestedPrefix);
                    String   addURLNested = getNestedURLStringForADD(nestedPrefix);
                    String  editURLNested = getNestedURLStringForEDIT(nestedPrefix);
                    String[] parentModels = getParentModels(parentResource);
                    int countOfActions = allowedActionNames.length;
                    for (int i = 0; i < countOfActions; i++) {
                        String action = allowedActionNames[i];
                        if (RouteConstants.ROUTE_ACTION_LIST_RESOURCES.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, name), indexURLNested, RouteConstants.ROUTE_HTTP_METHOD_GET));
                        }
                        else
                        if (RouteConstants.ROUTE_ACTION_ADD_RESOURCE.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, model), addURLNested, RouteConstants.ROUTE_HTTP_METHOD_GET));
                        }
                        else
                        if (RouteConstants.ROUTE_ACTION_CREATE_RESOURCE.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, model), indexURLNested, RouteConstants.ROUTE_HTTP_METHOD_POST));
                        }
                        else
                        if (RouteConstants.ROUTE_ACTION_READ_RESOURCE.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, model), curdURLNested, RouteConstants.ROUTE_HTTP_METHOD_GET));
                        }
                        else
                        if (RouteConstants.ROUTE_ACTION_EDIT_RESOURCE.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, model), editURLNested, RouteConstants.ROUTE_HTTP_METHOD_GET));
                        }
                        else
                        if (RouteConstants.ROUTE_ACTION_UPDATE_RESOURCE.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, model), curdURLNested, RouteConstants.ROUTE_HTTP_METHOD_PUT));
                        }
                        else
                        if (RouteConstants.ROUTE_ACTION_DELETE_RESOURCE.equals(action)) {
                            routes.add(createRestRoute(action, getTarget(parentModels, model), curdURLNested, RouteConstants.ROUTE_HTTP_METHOD_DELETE));
                        }
                    }
                }

                if (isStrictParent()) implicitPathPrefix = nestedPrefix;
            }
        }

        if (strictParent) return;

        //
        //create standard REST routes
        //
        String indexURL = getURLStringForList();
        String  curdURL = getURLStringForCRUD(indexURL);
        String   addURL = getURLStringForADD(indexURL);
        String  editURL = getURLStringForEDIT(indexURL);

        //
        //create member routes
        //
        Properties memberProperties =
            PropertyFileUtil.parseNestedPropertiesFromLine(member,
                    RouteConstants.PROPERTY_SYMBOL_GROUP_ITEM_ASSIGN,
                    RouteConstants.PROPERTY_SYMBOL_GROUP_ITEMS_DELIMITER);
        if (memberProperties != null) {
          for (Map.Entry<Object, Object> entry : memberProperties.entrySet()) {
                String action = (String)entry.getKey();
                String methods = (String)entry.getValue();
                methods = StringUtil.remove(methods, RouteConstants.PROPERTY_SYMBOL_ARRAY);
                routes.add(createRestRoute(action, model, curdURL + "/" + action, methods));
            }
        }

        //
        //create collection routes
        //
        Properties collectionProperties =
            PropertyFileUtil.parseNestedPropertiesFromLine(collection,
                    RouteConstants.PROPERTY_SYMBOL_GROUP_ITEM_ASSIGN,
                    RouteConstants.PROPERTY_SYMBOL_GROUP_ITEMS_DELIMITER);
        if (collectionProperties != null) {
          for (Map.Entry<Object, Object> entry : collectionProperties.entrySet()) {
                String action = (String)entry.getKey();
                String methods = (String)entry.getValue();
                methods = StringUtil.remove(methods, RouteConstants.PROPERTY_SYMBOL_ARRAY);
                routes.add(createRestRoute(action, name, indexURL + "/" + action, methods));
            }
        }

        //
        //create add routes
        //
        Properties addProperties =
            PropertyFileUtil.parseNestedPropertiesFromLine(add,
                    RouteConstants.PROPERTY_SYMBOL_GROUP_ITEM_ASSIGN,
                    RouteConstants.PROPERTY_SYMBOL_GROUP_ITEMS_DELIMITER);
        if (addProperties != null) {
          for (Map.Entry<Object, Object> entry : addProperties.entrySet()) {
                String action = (String)entry.getKey();
                String methods = (String)entry.getValue();
                methods = StringUtil.remove(methods, RouteConstants.PROPERTY_SYMBOL_ARRAY);
                routes.add(createRestRoute(action, model, indexURL + "/" + action, methods));
            }
        }

        //
        //create the seven standard rest routes
        //
        int count = allowedActionNames.length;
        for (int i = 0; i < count; i++) {
            String action = allowedActionNames[i];
            if (RouteConstants.ROUTE_ACTION_LIST_RESOURCES.equals(action)) {
                routes.add(createRestRoute(action, name, indexURL, RouteConstants.ROUTE_HTTP_METHOD_GET));
            }
            else
            if (RouteConstants.ROUTE_ACTION_ADD_RESOURCE.equals(action)) {
                routes.add(createRestRoute(action, model, addURL, RouteConstants.ROUTE_HTTP_METHOD_GET));
            }
            else
            if (RouteConstants.ROUTE_ACTION_CREATE_RESOURCE.equals(action)) {
                routes.add(createRestRoute(action, model, indexURL, RouteConstants.ROUTE_HTTP_METHOD_POST));
            }
            else
            if (RouteConstants.ROUTE_ACTION_READ_RESOURCE.equals(action)) {
                routes.add(createRestRoute(action, model, curdURL, RouteConstants.ROUTE_HTTP_METHOD_GET));
            }
            else
            if (RouteConstants.ROUTE_ACTION_EDIT_RESOURCE.equals(action)) {
                routes.add(createRestRoute(action, model, editURL, RouteConstants.ROUTE_HTTP_METHOD_GET));
            }
            else
            if (RouteConstants.ROUTE_ACTION_UPDATE_RESOURCE.equals(action)) {
                routes.add(createRestRoute(action, model, curdURL, RouteConstants.ROUTE_HTTP_METHOD_PUT));
            }
            else
            if (RouteConstants.ROUTE_ACTION_DELETE_RESOURCE.equals(action)) {
                routes.add(createRestRoute(action, model, curdURL, RouteConstants.ROUTE_HTTP_METHOD_DELETE));
            }
        }
    }

    private String[] updateActionNamesByExcept(String except) {
        int length = standardRestfulActionNames.length;
        String allowedActions = "";
        for (int i = 0; i < length; i++) {
            String action = standardRestfulActionNames[i];
            if (except.indexOf(action) == -1) {
                allowedActions += action + " ";
            }
        }
        return Converters.convertStringToStringArray(allowedActions, " ");
    }

    private RestRoute createRestRoute(String action, String target, String url, String methodsAllowed) {
        Route.validateMethods(methodsAllowed);

        Properties p = new Properties();
        p.put(RouteConstants.ROUTE_KEY_URL, url);
        p.put(RouteConstants.ROUTE_KEY_CONTROLLER, getController());
        p.put(RouteConstants.ROUTE_KEY_ACTION, action);
        p.put(RouteConstants.ROUTE_KEY_ALLOWED_METHODS, methodsAllowed);

        if (getSingular() != null) {
            p.put(RouteConstants.ROUTE_KEY_SINGULAR, getSingular());
        }

        if (getNamespace() != null) {
            p.put(RouteConstants.ROUTE_KEY_NAMESPACE, getNamespace());
        }

        if (getControllerClass() != null) {
            p.put(RouteConstants.ROUTE_KEY_CONTROLLER_CLASS, getControllerClass());
        }

        if (getRequirements() != null) {
            p.put(RouteConstants.ROUTE_KEY_REQUIREMENTS, requirements);
        }

        String routeName = createRestRouteName(action, target);
        RestRoute rr = new RestRoute(routeName, p);
        rr.setResourceName(this.name);
        rr.setModel(this.model);
        if(rr.getCacheable() == null) rr.cacheable = getDefaultCacheable(methodsAllowed);
        return rr;
    }
   
  private String getDefaultCacheable(String httpMethod) {
    return (RouteConstants.ROUTE_HTTP_METHOD_GET.equals(httpMethod))
        ? "true" : "false";
  }



    private String getURLStringForList() {
        return getScreenURLPattern();
    }

    private String getURLStringForCRUD(String indexURL) {
        return (!isSingle())?indexURL + "/" +
            ((autoRoute)?getDynamicPrimaryKeyRepresentation():RouteConstants.ROUTE_DEFAULT_ID):
                             indexURL;
    }

    private String getURLStringForADD(String indexURL) {
        return indexURL + "/" + getActionString("add");
    }

    private String getURLStringForEDIT(String indexURL) {
        return getURLStringForCRUD(indexURL) + "/" + getActionString("edit");
    }


    private Resource[] getParentResource(String[] parentResourceNames) {
        if (parentResourceNames == null) return null;
        int length = parentResourceNames.length;
        Resource[] resourceArray = new Resource[length];
        for (int i = 0; i < length; i++) {
            resourceArray[i] = getParentResource(parentResourceNames[i]);
        }
        return resourceArray;
    }

    private Resource getParentResource(String parentResourceName) {
        Resource resource = MatchMaker.getInstance().getResource(parentResourceName);
        if (resource == null) {
            resource = new Resource(parentResourceName, true);
            //throw new IllegalArgumentException("\"" + parentResourceName + "\"" +
            //            " is not defined as a resource, but is used as a" +
            //            " parent resource for \"" + getName() + "\".");
        }
        return resource;
    }



    private String getNestedURLPrefixString(Resource[] parents) {
        if (pathPrefix != null) return getURLStringForList();
        String nestedPath = "";
        int length = parents.length;
        for (int i = length-1; i >= 0; i--) {
            Resource parent = parents[i];
            String parentPath = (i == length-1)?
              parent.getScreenURLPattern() + "/" + "$" + getNesteeIdFormat(parent) :
              parent.getUnprifixedURL() + "/" + "$" + getNesteeIdFormat(parent);
            nestedPath += parentPath + "/";
        }
        nestedPath = StringUtil.replace(nestedPath, "//", "/");
        nestedPath = StringUtil.removeLastToken(nestedPath, "/");
        return nestedPath;
    }

    private String getNestedURLStringForList(String nestedPrefix) {
        String nestedPath = nestedPrefix;
        nestedPath += getUnprifixedURL();
        return nestedPath;
    }

    private String getNestedURLStringForCRUD(String nestedPrefix) {
        return (!isSingle())?getNestedURLStringForList(nestedPrefix) + "/" +
            ((autoRoute)?getDynamicPrimaryKeyRepresentation():RouteConstants.ROUTE_DEFAULT_ID):
                             getNestedURLStringForList(nestedPrefix);
    }

    private String getNestedURLStringForADD(String nestedPrefix) {
        return getNestedURLStringForList(nestedPrefix) + "/" + getActionString("add");
    }

    private String getNestedURLStringForEDIT(String nestedPrefix) {
        return getNestedURLStringForCRUD(nestedPrefix) + "/" + getActionString("edit");
    }

    private String[] getParentModels(Resource[] parentResource) {
        int length = parentResource.length;
        String[] models = new String[length];
        for (int i = 0; i < length; i++) {
            models[i] = parentResource[i].getModel();
        }
        return models;
    }


    private String getActionString(String action) {
        return (actionAliasProperties != null)?actionAliasProperties.getProperty(action, action):action;
    }

    private String getTarget(String[] parents, String target) {
        if (parents == null) return target;
        int length = parents.length;
        String nestedTarget = "";
        for (int i = length-1; i >= 0; i--) {
            nestedTarget += parents[i] + "-";
        }
        nestedTarget = StringUtil.removeLastToken(nestedTarget, "-");
        nestedTarget += "-" + target;
        return nestedTarget;
    }

    private String createRestRouteName(String action, String target) {
        return action + " " + target;
    }

    /**
     * <p>Uses the <tt>model</tt> field to retrieve and construct a dynamic
     * primary key representation for a record in route definition.</p>
     *
     * <p>The dynamic primary key representation should be like "$itemid",
     * or "$orderid-$itemid" if the primary key is a composite key consisting
     * of <tt>orderid</tt> and <tt>itemid</tt> fields. The separator between
     * key fields are defined by {@link com.scooterframework.web.route.RouteConstants#PRIMARY_KEY_SEPARATOR}.</p>
     *
     * <p>In the event that the <tt>model</tt> is not a table name, the
     * regular "$id" is used to represent dynamic primary key string.</p>
     */
    private String getDynamicPrimaryKeyRepresentation() {
        String tableName = (DatabaseConfig.getInstance().usePluralTableName())?WordUtil.tableize(model):model;

        List<String> columns = null;
        try {
          if (connName == null)
            connName = DatabaseConfig.getInstance().getDefaultDatabaseConnectionName();
            PrimaryKey pk = SqlExpressUtil.lookupPrimaryKey(connName, tableName);

            if (pk == null) {
                log.info("There is no primary key detected for table \"" +
                    tableName + "\" as it may be just a resource, " +
                    "not a real table, maybe a view. \"" +
                        RouteConstants.ROUTE_DEFAULT_ID +
                        "\" will be used to represent dynamic id for " +
                        model + " in the route definition instead.");
            }
            else {
                columns = pk.getColumns();
            }
        } catch(Exception ex) {
          log.error(ex);
        }

        String s = "";
        if (columns != null && columns.size() > 0) {
            Iterator<String> it = columns.iterator();
            while(it.hasNext()) {
                s += "$" + it.next().toLowerCase() + RouteConstants.PRIMARY_KEY_SEPARATOR;
            }
            s = StringUtil.removeLastToken(s, RouteConstants.PRIMARY_KEY_SEPARATOR);
        }
        else {
            s = RouteConstants.ROUTE_DEFAULT_ID;
        }
        return s;
    }
}
TOP

Related Classes of com.scooterframework.web.route.Resource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.