View Javadoc
1   /**
2    * This file Copyright (c) 2013-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.framework;
35  
36  import info.magnolia.config.source.ConfigurationSourceFactory;
37  import info.magnolia.config.source.yaml.YamlConfigurationSourceBuilder;
38  import info.magnolia.jcr.predicate.AbstractPredicate;
39  import info.magnolia.jcr.util.NodeUtil;
40  import info.magnolia.jcr.wrapper.ExtendingNodeWrapper;
41  import info.magnolia.module.ModuleLifecycle;
42  import info.magnolia.module.ModuleLifecycleContext;
43  import info.magnolia.module.ModuleRegistry;
44  import info.magnolia.objectfactory.Components;
45  import info.magnolia.ui.api.app.registry.AppDescriptorRegistry;
46  import info.magnolia.ui.api.app.registry.DefinitionTypes;
47  import info.magnolia.ui.dialog.DialogDefinitionRegistry;
48  import info.magnolia.ui.dialog.definition.ConfiguredFormDialogDefinition;
49  import info.magnolia.ui.form.fieldtype.registry.FieldTypeDefinitionRegistry;
50  import info.magnolia.ui.framework.app.contenttypes.AppWithContentType;
51  
52  import javax.inject.Inject;
53  import javax.jcr.Node;
54  import javax.jcr.RepositoryException;
55  
56  import lombok.SneakyThrows;
57  
58  /**
59   * Module class for UI framework.
60   */
61  public class UiFrameworkCompatibilityModule implements ModuleLifecycle {
62  
63      private final ConfigurationSourceFactory configSourceFactory;
64      private final FieldTypeDefinitionRegistry fieldTypeDefinitionRegistry;
65      private final DialogDefinitionRegistry dialogDefinitionRegistry;
66      private final AppDescriptorRegistry appDescriptorRegistry;
67      private final ModuleRegistry moduleRegistry;
68  
69      @Inject
70      public UiFrameworkCompatibilityModule(ConfigurationSourceFactory configSourceFactory,
71                                            FieldTypeDefinitionRegistry fieldTypeDefinitionRegistry,
72                                            DialogDefinitionRegistry dialogDefinitionRegistry,
73                                            AppDescriptorRegistry appDescriptorRegistry,
74                                            ModuleRegistry moduleRegistry) {
75  
76          this.configSourceFactory = configSourceFactory;
77          this.fieldTypeDefinitionRegistry = fieldTypeDefinitionRegistry;
78          this.dialogDefinitionRegistry = dialogDefinitionRegistry;
79          this.appDescriptorRegistry = appDescriptorRegistry;
80          this.moduleRegistry = moduleRegistry;
81      }
82  
83      @Override
84      public void start(ModuleLifecycleContext context) {
85          if (context.getPhase() == ModuleLifecycleContext.PHASE_SYSTEM_STARTUP) {
86  
87              /**
88               * TODO Address loading order of these registries because of validators in MGNLUI-4770.
89               * Dialog registry is temporarily moved after field type registry because dialogs depend on field types
90               * to be perfectly built.
91               */
92              configSourceFactory.jcr().withFilter(new IsFieldType()).bindWithDefaults(fieldTypeDefinitionRegistry);
93              configSourceFactory.yaml().bindWithDefaults(fieldTypeDefinitionRegistry);
94  
95              configSourceFactory.jcr().withFilter(new IsDialogNode()).bindWithDefaults(dialogDefinitionRegistry);
96              configSourceFactory.yaml().bindWithDefaults(dialogDefinitionRegistry);
97  
98              configSourceFactory.jcr().withFilter(new IsAppDescriptor()).bindWithDefaults(appDescriptorRegistry);
99              YamlConfigurationSourceBuilder appConfigurationSource = configSourceFactory.yaml();
100             if (moduleRegistry.isModuleRegistered("content-types")) {
101                 AppWithContentType generatedAppConstruct = Components.newInstance(AppWithContentType.class);
102                 appConfigurationSource.withCustomMultiConstruct(AppWithContentType.TAG_PREFIX, generatedAppConstruct);
103             }
104             appConfigurationSource.bindWithDefaults(appDescriptorRegistry);
105         }
106     }
107 
108     @Override
109     public void stop(ModuleLifecycleContext context) {
110     }
111 
112     /**
113      * Check if this node can be handled as an {@link info.magnolia.ui.api.app.AppDescriptor}.
114      * Prior to 5.4, this was in {@link info.magnolia.ui.api.app.registry.ConfiguredAppDescriptorManager}.
115      */
116     private static class IsAppDescriptor extends AbstractPredicate<Node> {
117         @Override
118         public boolean evaluateTyped(Node node) {
119             try {
120                 if (node.hasProperty(ConfiguredFormDialogDefinition.EXTEND_PROPERTY_NAME)) {
121                     node = new ExtendingNodeWrapper(node);
122                 }
123                 return DefinitionTypes.APP.getPluralName().equalsIgnoreCase(node.getParent().getName());
124             } catch (RepositoryException e) {
125                 throw new RuntimeException(e);
126             }
127         }
128     }
129 
130     /**
131      * Check if this node can be handled as an {@link info.magnolia.ui.form.fieldtype.definition.FieldTypeDefinition}.
132      * Prior to 5.4, this was in {@link info.magnolia.ui.form.fieldtype.registry.ConfiguredFieldTypeDefinitionManager}.
133      */
134     private static class IsFieldType extends AbstractPredicate<Node> {
135 
136         public static final String DEFINITION_CLASS = "definitionClass";
137 
138         public static final String FACTORY_CLASS = "factoryClass";
139 
140         @Override
141         public boolean evaluateTyped(Node node) {
142             try {
143                 if (node.hasProperty(ConfiguredFormDialogDefinition.EXTEND_PROPERTY_NAME)) {
144                     node = new ExtendingNodeWrapper(node);
145                 }
146                 return node.hasProperty(DEFINITION_CLASS) && node.hasProperty(FACTORY_CLASS);
147             } catch (RepositoryException e) {
148                 throw new RuntimeException(e);
149             }
150         }
151     }
152 
153     /**
154      * Check if this node can be handled as a dialog.
155      */
156     public static class IsDialogNode extends AbstractPredicate<Node> {
157         @SneakyThrows(RepositoryException.class)
158         @Override
159         public boolean evaluateTyped(Node node) {
160             if (node.hasProperty("extends") && !NodeUtil.isWrappedWith(node, ExtendingNodeWrapper.class)) {
161                 node = new ExtendingNodeWrapper(node);
162             }
163             return node.hasNode("form") || node.hasNode("actions");
164         }
165     }
166 }