    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005// http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.services;
    014
    015import org.apache.tapestry5.Asset;
    016import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
    017import org.apache.tapestry5.ioc.annotations.UsesConfiguration;
    018import org.apache.tapestry5.ioc.services.ClassNameLocator;
    019import org.apache.tapestry5.services.transform.ControlledPackageType;
    020
    021import java.util.Collection;
    022import java.util.List;
    023import java.util.Map;
    024
    025/**
    026 * Resolves page names and component types to fully qualified class names. Pages and components may be provided by the
    027 * application or inside a <em>mapped package</em>. Page names often appear inside URLs, and component types often
    028 * appear in component templates (when specifying the type of an embedded component).
    029 *
    030 * The service is configured using a collection of {@link LibraryMapping}s. Each mapping maps a prefix, such as "core"
    031 * to a root package name, such as "org.apache.tapestry5.corelib". The root package is expected to have sub-packages:
    032 * "pages", "components", "mixins" and "base" ("base" is for base classes).
    033 *
    034 * The resolver performs a search of the classpath (via {@link ClassNameLocator}), to build up a set of case-insensitive
    035 * maps from logical page name, component type, or mixin type to fully qualified class name.
    036 *
    037 * Certain ambiguities occur if mapped packages overlap, either in terms of the the prefixes or the package names. Keep
    038 * things clearly separate to avoid lookup problems.
    039 */
    040@UsesConfiguration(LibraryMapping.class)
    041public interface ComponentClassResolver
    042{
    043    /**
    044     * Converts a logical page name (such as might be encoded into a URL) into a fully qualified class name. The case of
    045     * the page name is irrelevant.
    046     *
    047     * @param pageName
    048     *         page name
    049     * @return fully qualified class name for the page
    050     * @throws org.apache.tapestry5.commons.util.UnknownValueException
    051     *         if the name does not match a known page class
    052     */
    053    String resolvePageNameToClassName(String pageName);
    054
    055    /**
    056     * For a particular path, determines if the path is a logical page name. The check is case insensitive.
    057     *
    058     * @param pageName
    059     *         potential logical page name
    060     * @return true if the page name is valid
    061     */
    062    boolean isPageName(String pageName);
    063
    064    /**
    065     * Returns a list of all page names, in sorted order. These are the "canonical" page names.
    066     */
    067    List<String> getPageNames();
    068
    069    /**
    070     * Returns a list of all component names, in sorted order. These are the "canonical" component names.
    071     * @since 5.4
    072     */
    073    @IncompatibleChange(release = "5.4", details = "added method")
    074    List<String> getComponentNames();
    075
    076    /**
    077     * Returns a list of all mixin names, in sorted order. These are the "canonical" mixin names.
    078     * @since 5.4
    079     */
    080    @IncompatibleChange(release = "5.4", details = "added method")
    081    List<String> getMixinNames();
    082
    083    /**
    084     * Converts a fully qualified page class name into a page name (often, for inclusion as part of the URI). This value
    085     * may later be passed to {@link #resolvePageNameToClassName(String)}.
    086     *
    087     * @param pageClassName
    088     *         fully qualified name of a page class
    089     * @return equivalent logical page name
    090     * @throws IllegalArgumentException
    091     *         if the name can not be resolved
    092     */
    093    String resolvePageClassNameToPageName(String pageClassName);
    094
    095    /**
    096     * Returns the canonical form of a page name. The canonical form uses character case matching the underlying class
    097     * name.
    098     *
    099     * @throws org.apache.tapestry5.commons.util.UnknownValueException
    100     *         if the page name does not match a logical page name
    101     */
    102    String canonicalizePageName(String pageName);
    103
    104    /**
    105     * Converts a component type (a logical component name such as might be used inside a template or annotation) into a
    106     * fully qualified class name. Case is ignored in resolving the name.
    107     *
    108     * @param componentType
    109     *         a logical component type
    110     * @return fully qualified class name
    111     * @throws org.apache.tapestry5.commons.util.UnknownValueException
    112     *         if the component type can not be resolved
    113     */
    114    String resolveComponentTypeToClassName(String componentType);
    115
    116    /**
    117     * Converts a logical mixin type (as with component types) into a fully qualified class name. Case is ignored when
    118     * resolving the name.
    119     *
    120     * @param mixinType
    121     *         a logical mixin type
    122     * @return fully qualified class name
    123     * @throws org.apache.tapestry5.commons.util.UnknownValueException
    124     *         if the mixin type can not be resolved
    125     */
    126    String resolveMixinTypeToClassName(String mixinType);
    127
    128    /**
    129     * A mapping from virtual folder name to a package name (used for converting classpath {@link Asset}s
    130     * to client URLs). This is derived from the contributed {@link LibraryMapping}s.
    131     *
    132     * It is allowed to contribute multiple root packages as a single folder name. In this case, the best common package
    133     * name is used. For example, if both <code>com.example.main</code> and <code>com.example.extras</code> is mapped to
    134     * folder "example", then the package mapping for "example" will be <code>com.example</code>.
    135     *
    136     * @see ClasspathAssetAliasManager
    137     * @since 5.2.0
    138     */
    139    Map<String, String> getFolderToPackageMapping();
    140
    141    /**
    142     * Returns the names of all libraries (as {@linkplain org.apache.tapestry5.services.LibraryMapping#getPathPrefix() configured}).
    143     * This does not include the application itself (which is a library with the virtual path of empty string).
    144     *
    145     * @return sorted names of libraries
    146     * @since 5.4
    147     */
    148    List<String> getLibraryNames();
    149
    150    /**
    151     * Used to identify which packages are controlled packages (from which components are loaded). Future expansion
    152     * may allow for additional packages which are live reloaded but not components (or perhaps are transformed, but not
    153     * as components).
    154     *
    155     * @return a mapping from package name to {@link ControlledPackageType}.
    156     * @since 5.3
    157     */
    158    Map<String, ControlledPackageType> getControlledPackageMapping();
    159
    160    /**
    161     * Returns true if the class name is specifically a page class, and not a component, mixin or base class.
    162     *
    163     * @param pageClassName
    164     * @return true if a page class
    165     * @since 5.3
    166     */
    167    boolean isPage(final String pageClassName);
    168
    169    /**
    170     * Given a class name of a component class, returns the library name (as defined by a
    171     * {@linkplain org.apache.tapestry5.services.LibraryMapping#getPathPrefix() contributed library name}).
    172     *
    173     * @param className
    174     * @return library name
    175     * @throws IllegalArgumentException
    176     *         if the class can't be matched to a contributed root package
    177     */
    178    String getLibraryNameForClass(String className);
    179
    180    /**
    181     * Returns the library mappings.
    182     */
    183    @IncompatibleChange(release = "5.4", details = "Added method")
    184    Collection<LibraryMapping> getLibraryMappings();
    185
    186    /**
    187     * Returns the logical name for a page, component or mixin fully classified class name.
    188     */
    189    @IncompatibleChange(release = "5.8.3", details = "Added method")
    190    public String getLogicalName(String className);
    191
    192    /**
    193     * Returns the class name for a page, component or class given its logical name.
    194     */
    195    @IncompatibleChange(release = "5.8.3", details = "Added method")
    196    String getClassName(String logicalName);
    197}