[ https://issues.apache.org/jira/browse/TRINIDAD-2406?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13790143#comment-13790143 ]
Anand V Nath commented on TRINIDAD-2406: ---------------------------------------- API and internal changes for implementing this are: 1. Create an object to capture metadata about skin: org.apache.myfaces.trinidad.skin.SkinMetadata public final class SkinMetadata { SkinMetadata(id, family, renderKit, parentSkin, ... ) public String getBaseSkinId() public String getId() public String getFamily() public String getRenderKit() public SkinVersion getVersion() public SkinFeatures getFeatures() public CustomMetadata getMetadata() public String getStyleSheetName() public String getResourceBundleName() public ValueExpression getTranslationSource() } Include a static inner builder class for: org.apache.myfaces.trinidad.skin.SkinMetadata, org.apache.myfaces.trinidad.skin.SkinMetadata.Builder for easy instantiation of the SkinMetadata. Since we have too many parameters to be captured for SkinMetadata, we use a builder. public final class SkinMetadata { private SkinMetadata(Builder b) { } ... public static final class Builder { public Builder() // setters for optional items public Builder id(String id) public Builder family(String family) public Builder parent(String parent) public Builder version(SkinVersion version) public Builder styleSheetName(String styleSheetName) public Builder resourceBundleName(String resourceBundleName) public Builder translationSource(ValueExpression translationSource) public Builder baseSkinId(String baseSkinId) public Builder feature(SkinFeatures features) public Builder metadata(CustomMetadata metadata) // build method to create SkinMetadata object public SkinMetadata build() } } For example the client code would look like: new SkinMetadata.Builder().id(skinId).family(family).renderKitId(renderKitId).version(version).build(); 2. Create org.apache.myfaces.trinidad.skin.SkinProvider SPI public abstract class SkinProvider { /** * Returns the Skin for the given skin ID. * * The returned skin is not cached by the framework and thus it * is the responsibility of the provider to return the same instance * of the skin should it desire so. */ public abstract Skin getSkin(FacesContext context, SkinMetadata metadata) /** * A provider can optionally return information about some or all of the skins it provides. * Typically this information is generated without loading the skins * as this is a quick way to find out about the Skins in the provider and also thereby * supporting lazy loading of Skins. * SkinMetadata for a Skin should contain only features and metadata that it * explicitly supports. It should not contain the features and metadata that * belongs only to its parent skins. * @param context * @return */ public Collection<SkinMetadata> getSkinMetadata(FacesContext context) { return Collections.emptyList(); } } 3. org.apache.myfaces.trinidadinternal.skin.provider.BaseSkinProvider extends org.apache.myfaces.trinidad.skin.SkinProvider to abstract all common functionality of trinidad internal providers. public abstract class BaseSkinProvider extends SkinProvider { public Skin getSkin(FacesContext context, SkinMetadata skinMetadata) { // common implementation shared between the internal trinidad skin providers. } public Collection<SkinMetadata> getSkinMetadata(FacesContext context) { // common implementation shared between the internal trinidad skin providers. } } 4. Implement org.apache.myfaces.trinidadinternal.skin.provider.TrinidadBaseSkinProvider extends BaseSkinProvider to load all trinidad base skins and to be consistent with the SPI - This extracts logic from SkinUtils.registerBaseSkins public final class TrinidadBaseSkinProvider extends BaseSkinProvider { // Implement the methods for handling all base trinidad skins currently registered using SkinUtils.registerBaseSkins } 5. Implement org.apache.myfaces.trinidadinternal.skin.provider.TrinidadSkinProvider extends BaseSkinProvider to read all the trinidad-skins.xml - This will consolidate code from SkinUtils.registerSkinExtensions public final class TrinidadSkinProvider extends BaseSkinProvider { // Implement the methods for handling all skins defined using trinidad-skins.xml // use this class as a wrapper on top on SkinFactory // remove any pre caching done in SkinFactory // load skins from SkinFactory only on need basis public Collection<SkinMetadata> getSkinMetadata() { // return the information inside trinidad-skins.xml } } 6. Implement org.apache.myfaces.trinidadinternal.skin.provider.ExternalSkinProvider extends BaseSkinProvider to handle all externally registered skins using SkinFactory.addSkin and SkinFactory.reload routiens. public final class ExternalSkinProviderextends BaseSkinProvider { // this provider supports reload and addSkin as required by SkinFactory. // SkinFactoryImpl will now call this class for its operations. // and SkinFactoryImpl will serve only such externally registered skins. // all other skins like trinidad-skins.xml and base skins will be served by // their respective providers. } 7. Implement org.apache.myfaces.trinidad.skin.SkinProviderRegistry which is a one point API to load all kinds of SkinProviders - This API will query the SPIs to return the requested skin. public final class SkinProviderRegistry implementes SkinProvider { public static SkinProvider getInstance(); // for any getSkin API, query the registered SPIs followed by TrinidadSkinProvider and TrinidadBaseSkinProvider // This gives a chance for the registered SPIs to return their skin in front of the default skins. // current implementation assumes that there will not be any collision for getSkin API based on skin-id, family, name, renderkit etc // solve this problem as an when it arises public Collection<SkinMetadata> getSkinMetadata() { // return the consolidated information from all registered SkinProvider SPIs } } 8. Expose SkinExtension creation via SkinFactory /** * Creates a skin extension based on the supplied baseSkin and the information from supplied skinMetadata * The base skin supplied should be one that is queried out of SkinProvider. * @param context * @param baseSkinMetadata search criteria for the base skin * @param skinMetadata metadata to create new skin extension * @return a new SkinExtension object created using the skinMetadata supplied * @throws IllegalArgumentException if the baseSkinId contained in the supplied skinMetadata did not match the id of the supplied baseSkin * @throws ClassCastException if the base skin supplied is not one queried out of SkinProvider. */ public Skin createSkin(FacesContext context, SkinMetadata baseSkinMetadata, SkinMetadata skinMetadata) /** * Creates a skin extension based on the information from supplied skinMetadata. Id of the base skin for the new * skin extension has to be set in the metadata. * @param context * @param skinMetadata metadata to create new skin extension * @return a new SkinExtension object createed using the skinMetadata supplied * @throws IllegalArgumentException if the baseSkinId contained in the supplied skinMetadata did not match the id of the supplied baseSkin */ public Skin createSkin(FacesContext context, SkinMetadata skinMetadata) 9. Modify org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl not to init the skins using org.apache.myfaces.trinidad.skin.SkinFactory 10. Modify the callers which uses org.apache.myfaces.trinidad.skin.SkinFactory to query skins to use the new SkinProvider. 11. Deprecate all methods in org.apache.myfaces.trinidad.skin.SkinFactory execpt for the new createSkin methods 12. Modify org.apache.myfaces.trinidad.skin.SkinFactory to fall back on SkinProvider and ExternalSkinProvide for all its operations. 13. Deprecate org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl.reloadSkins since reloading of a skin is SkinProvider internal implementation. 14. Remove org.apache.myfaces.trinidadinternal.skin.SkinUtils APIs like registerBaseSkins, registerSkinExtensions which are moved. 15. Add APIs to org.apache.myfaces.trinidadinternal.skin.SkinUtils to return the parsed information from trinidad-skins.xml. This will be used by internal trinidad SkinProvider. 16. Remove duplication in parsing code by using SkinMetadata, SkinAddition, SkinVersion etc which are already part of public API instead of SkinVersionNode, SkinAdditionNode, SkinNode etc. > externalize skin repositories by using SkinProvider SPI > ------------------------------------------------------- > > Key: TRINIDAD-2406 > URL: https://issues.apache.org/jira/browse/TRINIDAD-2406 > Project: MyFaces Trinidad > Issue Type: Improvement > Components: Skinning > Affects Versions: 2.1.0-core > Reporter: Anand V Nath > > Introduce SkinProvider SPI. Users can use this to create their own skip > repositories and expose their skins to the skinning framework. > Provide an API to query skin using skin family, skin id, render kit - This > will make use of the existing SkinFactory APIs. Only change here is that it > should go over all the available SkinProvider SPIs to find a match. > Create internal SkinProvider SPIs to handle the Trinidad and RCF skins (or > skins defined using trinidad-skins.xml). > Provide an API to list all the available skins from all SkinProvider SPIs and > make the skin metadata thus available. > Make SkinExtension part of public API so that users can use this class to > create the Skin objects which they expose through their SkinProvider SPIs -- This message was sent by Atlassian JIRA (v6.1#6144)