/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.deltaspike.jsf.impl.config.view; import org.apache.deltaspike.core.api.config.view.DefaultErrorView; import org.apache.deltaspike.core.api.config.view.ViewConfig; import org.apache.deltaspike.core.api.config.view.metadata.ConfigDescriptor; import org.apache.deltaspike.core.spi.config.view.ConfigDescriptorValidator; import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigDescriptor; import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver; import org.apache.deltaspike.core.spi.config.view.ConfigNodeConverter; import org.apache.deltaspike.core.spi.config.view.ViewConfigInheritanceStrategy; import org.apache.deltaspike.core.spi.config.view.ViewConfigNode; import org.apache.deltaspike.jsf.api.config.view.Folder; import org.apache.deltaspike.jsf.api.config.view.View; import org.apache.deltaspike.jsf.api.literal.FolderLiteral; import org.apache.deltaspike.jsf.api.literal.ViewLiteral; import org.apache.deltaspike.jsf.impl.util.ViewConfigUtils; import javax.enterprise.inject.Typed; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; @Typed() public class DefaultViewConfigResolver implements ViewConfigResolver { private Map<Class<? extends ViewConfig>, ViewConfigDescriptor> viewDefinitionToViewDefinitionEntryMapping; private Map<String, ViewConfigDescriptor> viewPathToViewDefinitionEntryMapping; private Map<Class, ConfigDescriptor> folderDefinitionToViewDefinitionEntryMapping; private Map<String, ConfigDescriptor> folderPathToViewDefinitionEntryMapping; private ViewConfigDescriptor defaultErrorView; public DefaultViewConfigResolver(ViewConfigNode rootViewConfigNode, ConfigNodeConverter configNodeConverter, ViewConfigInheritanceStrategy inheritanceStrategy, List<ConfigDescriptorValidator> configDescriptorValidators) { Map<Class<? extends ViewConfig>, ViewConfigDescriptor> viewConfigs = new HashMap<Class<? extends ViewConfig>, ViewConfigDescriptor>(); Map<Class, ConfigDescriptor> folderConfigs = new HashMap<Class, ConfigDescriptor>(); Map<String, Class<? extends ViewConfig>> foundViewIds = new HashMap<String, Class<? extends ViewConfig>>(); Stack<ViewConfigNode> nodesToConvert = new Stack<ViewConfigNode>(); nodesToConvert.addAll(rootViewConfigNode.getChildren()); while (!nodesToConvert.empty()) { ViewConfigNode currentNode = nodesToConvert.pop(); //e.g. @View is optional for users, but required from other parts of DeltaSpike -> ensure that it's in place addOptionalMetaDataToConfig(currentNode); currentNode.getInheritedMetaData().addAll(inheritanceStrategy.resolveInheritedMetaData(currentNode)); ConfigDescriptor currentConfigDescriptor = configNodeConverter.convert(currentNode); for (ConfigDescriptorValidator validator : configDescriptorValidators) { if (!validator.isValid(currentConfigDescriptor)) { throw new IllegalStateException(currentConfigDescriptor.getConfigClass().getName() + " is invalid"); } } if (currentConfigDescriptor instanceof ViewConfigDescriptor) { ViewConfigDescriptor currentViewConfigDescriptor = (ViewConfigDescriptor) currentConfigDescriptor; if (foundViewIds.containsKey(currentViewConfigDescriptor.getViewId())) { throw new IllegalStateException(currentViewConfigDescriptor.getViewId() + " is configured twice. " + "That isn't allowed - see: " + currentConfigDescriptor.getConfigClass().getName() + " and " + foundViewIds.get(currentViewConfigDescriptor.getViewId()).getName()); } else { foundViewIds.put( currentViewConfigDescriptor.getViewId(), currentViewConfigDescriptor.getConfigClass()); } if (this.defaultErrorView == null) { if (DefaultErrorView.class.isAssignableFrom(currentViewConfigDescriptor.getConfigClass())) { this.defaultErrorView = currentViewConfigDescriptor; } } else if (DefaultErrorView.class.isAssignableFrom(currentViewConfigDescriptor.getConfigClass())) { throw new IllegalStateException("It isn't allowed to configure multiple default-error-views. " + "Found default-error-views: " + this.defaultErrorView.getConfigClass() + " and " + currentViewConfigDescriptor.getConfigClass().getName()); } if (!viewConfigs.containsKey(currentViewConfigDescriptor.getConfigClass())) { viewConfigs.put(currentViewConfigDescriptor.getConfigClass(), currentViewConfigDescriptor); } } else { if (!folderConfigs.containsKey(currentConfigDescriptor.getConfigClass())) { folderConfigs.put(currentConfigDescriptor.getConfigClass(), currentConfigDescriptor); } } nodesToConvert.addAll(currentNode.getChildren()); } this.viewDefinitionToViewDefinitionEntryMapping = Collections.unmodifiableMap(viewConfigs); this.folderDefinitionToViewDefinitionEntryMapping = Collections.unmodifiableMap(folderConfigs); initCaches(); } protected void addOptionalMetaDataToConfig(ViewConfigNode currentNode) { Class sourceClass = currentNode.getSource(); if (ViewConfigUtils.isFolderConfig(sourceClass)) { for (Annotation annotation : currentNode.getMetaData()) { if (annotation.annotationType().equals(Folder.class)) { return; } } currentNode.getMetaData().add(new FolderLiteral(true)); return; } for (Annotation annotation : currentNode.getMetaData()) { if (annotation.annotationType().equals(View.class)) { return; } } currentNode.getMetaData().add(new ViewLiteral(true)); } @Override public ConfigDescriptor<?> getConfigDescriptor(String path) { if (path == null) { return null; } ConfigDescriptor result = this.folderPathToViewDefinitionEntryMapping.get(path); if (result == null) { result = getViewConfigDescriptor(path); //TODO re-visit it } return result; } @Override public ViewConfigDescriptor getViewConfigDescriptor(String viewId) { if (viewId == null) { return null; } return this.viewPathToViewDefinitionEntryMapping.get(viewId); } @Override public ConfigDescriptor<?> getConfigDescriptor(Class configClass) { ConfigDescriptor result = null; if (ViewConfig.class.isAssignableFrom(configClass)) { result = getViewConfigDescriptor(configClass); } if (result == null) { result = this.folderDefinitionToViewDefinitionEntryMapping.get(configClass); } return result; } @Override public List<ConfigDescriptor<?>> getConfigDescriptors() { ConfigDescriptor<?>[] folderResult = this.folderDefinitionToViewDefinitionEntryMapping.values() .toArray(new ConfigDescriptor<?>[this.folderDefinitionToViewDefinitionEntryMapping.size()]); ConfigDescriptor<?>[] viewResult = this.viewDefinitionToViewDefinitionEntryMapping.values() .toArray(new ConfigDescriptor<?>[this.viewDefinitionToViewDefinitionEntryMapping.size()]); List<ConfigDescriptor<?>> result = new ArrayList<ConfigDescriptor<?>>(); result.addAll(Arrays.asList(folderResult)); result.addAll(Arrays.asList(viewResult)); return result; } @Override public ViewConfigDescriptor getViewConfigDescriptor(Class<? extends ViewConfig> viewDefinitionClass) { if (DefaultErrorView.class.equals(viewDefinitionClass)) { return getDefaultErrorViewConfigDescriptor(); } return this.viewDefinitionToViewDefinitionEntryMapping.get(viewDefinitionClass); } @Override public List<ViewConfigDescriptor> getViewConfigDescriptors() { ViewConfigDescriptor[] result = this.viewDefinitionToViewDefinitionEntryMapping.values() .toArray(new ViewConfigDescriptor[this.viewDefinitionToViewDefinitionEntryMapping.size()]); return new ArrayList<ViewConfigDescriptor>(Arrays.asList(result)); } @Override public ViewConfigDescriptor getDefaultErrorViewConfigDescriptor() { return this.defaultErrorView; } protected void initCaches() { //folders Map<String, ConfigDescriptor> folderPathMapping = new HashMap<String, ConfigDescriptor>(); for (ConfigDescriptor folderConfigDescriptor : this.folderDefinitionToViewDefinitionEntryMapping.values()) { if (folderPathMapping.containsKey(folderConfigDescriptor.toString())) { throw new IllegalStateException("Duplicated config for the same folder configured. See: " + folderPathMapping.get( folderConfigDescriptor.toString()).getConfigClass().getName() + " and " + folderConfigDescriptor.getConfigClass().getName()); } folderPathMapping.put(folderConfigDescriptor.getPath(), folderConfigDescriptor); } this.folderPathToViewDefinitionEntryMapping = Collections.unmodifiableMap(folderPathMapping); //pages Map<String, ViewConfigDescriptor> viewPathMapping = new HashMap<String, ViewConfigDescriptor>(); for (ViewConfigDescriptor pageConfigDescriptor : this.viewDefinitionToViewDefinitionEntryMapping.values()) { if (viewPathMapping.containsKey(pageConfigDescriptor.getViewId())) { throw new IllegalStateException("Duplicated config for the same page configured. See: " + viewPathMapping.get( pageConfigDescriptor.getViewId()).getConfigClass().getName() + " and " + pageConfigDescriptor.getConfigClass().getName()); } viewPathMapping.put(pageConfigDescriptor.getPath(), pageConfigDescriptor); } this.viewPathToViewDefinitionEntryMapping = Collections.unmodifiableMap(viewPathMapping); } }