001 // Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.services;
016
017 import java.util.List;
018 import java.util.Map;
019
020 import org.apache.tapestry5.Asset;
021 import org.apache.tapestry5.ioc.annotations.UsesConfiguration;
022 import org.apache.tapestry5.ioc.services.ClassNameLocator;
023 import org.apache.tapestry5.services.transform.ControlledPackageType;
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 template (when specifying the type of an embedded component).
029 * <p/>
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 * <p/>
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 * <p/>
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)
041 public 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.ioc.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.
066 */
067 List<String> getPageNames();
068
069 /**
070 * Converts a fully qualified page class name into a page name (often, for inclusion as part of the URI). This value
071 * may later be passed to {@link #resolvePageNameToClassName(String)}.
072 *
073 * @param pageClassName
074 * fully qualified name of a page class
075 * @return equivalent logical page name
076 * @throws IllegalArgumentException
077 * if the name can not be resolved
078 */
079 String resolvePageClassNameToPageName(String pageClassName);
080
081 /**
082 * Returns the canonical form of a page name. The canonical form uses character case matching the underlying class
083 * name.
084 *
085 * @throws org.apache.tapestry5.ioc.util.UnknownValueException
086 * if the page name does not match a logical page name
087 */
088 String canonicalizePageName(String pageName);
089
090 /**
091 * Converts a component type (a logical component name such as might be used inside a template or annotation) into a
092 * fully qualified class name. Case is ignored in resolving the name.
093 *
094 * @param componentType
095 * a logical component type
096 * @return fully qualified class name
097 * @throws org.apache.tapestry5.ioc.util.UnknownValueException
098 * if the component type can not be resolved
099 */
100 String resolveComponentTypeToClassName(String componentType);
101
102 /**
103 * Converts a logical mixin type (as with component types) into a fully qualified class name. Case is ignored when
104 * resolving the name.
105 *
106 * @param mixinType
107 * a logical mixin type
108 * @return fully qualified class name
109 * @throws org.apache.tapestry5.ioc.util.UnknownValueException
110 * if the mixin type can not be resolved
111 */
112 String resolveMixinTypeToClassName(String mixinType);
113
114 /**
115 * A mapping from virtual folder name to a package name (used for converting classpath {@link Asset}s
116 * to client URLs). This is derived from the contributed {@link LibraryMapping}s.
117 * <p>
118 * It is allowed to contribute multiple root packages as a single folder name. In this case, the best common package
119 * name is used. For example, if both <code>com.example.main</code> and <code>com.example.extras</code> is mapped to
120 * folder "example", then the package mapping for "example" will be <code>com.example</code>.
121 *
122 * @since 5.2.0
123 * @see ClasspathAssetAliasManager
124 */
125 Map<String, String> getFolderToPackageMapping();
126
127 /**
128 * Used to identify which packages are controlled packages (from which components are loaded). Future expansion
129 * may allow for additional packages which are live reloaded but not components (or perhaps are transformed, but not
130 * as components).
131 *
132 * @return a mapping from package name to {@link ControlledPackageType}.
133 * @since 5.3
134 */
135 Map<String, ControlledPackageType> getControlledPackageMapping();
136
137 /**
138 * Returns true if the class name is specifically a page class, and not a component, mixin or base class.
139 *
140 * @param pageClassName
141 * @return true if a page class
142 * @since 5.3
143 */
144 boolean isPage(final String pageClassName);
145 }