View Javadoc
1   /**
2    * This file Copyright (c) 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.form.definition;
35  
36  import info.magnolia.dynamic.MagnoliaProxy;
37  import info.magnolia.ui.api.action.ActionDefinition;
38  import info.magnolia.ui.api.action.ConfiguredActionDefinition;
39  import info.magnolia.ui.contentapp.action.CloseActionDefinition;
40  import info.magnolia.ui.contentapp.action.CommitActionDefinition;
41  import info.magnolia.ui.dialog.ConfiguredFormDialogDefinition;
42  import info.magnolia.ui.dialog.DialogDefinition;
43  import info.magnolia.ui.dialog.action.CancelDialogActionDefinition;
44  import info.magnolia.ui.dialog.action.SaveDialogActionDefinition;
45  import info.magnolia.ui.field.ConfiguredNamedFieldDefinition;
46  import info.magnolia.ui.field.EditorPropertyDefinition;
47  import info.magnolia.ui.field.NamedFieldDefinition;
48  import info.magnolia.ui.editor.ConfiguredFormDefinition;
49  import info.magnolia.ui.editor.FormDefinition;
50  import info.magnolia.ui.form.action.CancelFormActionDefinition;
51  import info.magnolia.ui.form.action.SaveFormActionDefinition;
52  import info.magnolia.ui.form.field.definition.BasicTextCodeFieldDefinition;
53  import info.magnolia.ui.form.field.definition.BasicUploadFieldDefinition;
54  import info.magnolia.ui.form.field.definition.CheckboxFieldDefinition;
55  import info.magnolia.ui.form.field.definition.CodeFieldDefinition;
56  import info.magnolia.ui.form.field.definition.CompositeFieldDefinition;
57  import info.magnolia.ui.form.field.definition.DateFieldDefinition;
58  import info.magnolia.ui.form.field.definition.HiddenFieldDefinition;
59  import info.magnolia.ui.form.field.definition.LinkFieldDefinition;
60  import info.magnolia.ui.form.field.definition.MultiValueFieldDefinition;
61  import info.magnolia.ui.form.field.definition.OptionGroupFieldDefinition;
62  import info.magnolia.ui.form.field.definition.RichTextFieldDefinition;
63  import info.magnolia.ui.form.field.definition.SelectFieldDefinition;
64  import info.magnolia.ui.form.field.definition.StaticFieldDefinition;
65  import info.magnolia.ui.form.field.definition.SwitchableFieldDefinition;
66  import info.magnolia.ui.form.field.definition.TextFieldDefinition;
67  import info.magnolia.ui.form.field.definition.TwinColSelectFieldDefinition;
68  import info.magnolia.ui.form.field.definition.migration.CheckboxFieldDefinitionConverter;
69  import info.magnolia.ui.form.field.definition.migration.CodeFieldDefinitionConverter;
70  import info.magnolia.ui.form.field.definition.migration.CompositeFieldDefinitionConverter;
71  import info.magnolia.ui.form.field.definition.migration.DateFieldDefinitionConverter;
72  import info.magnolia.ui.form.field.definition.migration.FieldDefinitionConverter;
73  import info.magnolia.ui.form.field.definition.migration.FallbackFieldDefinitionConverter;
74  import info.magnolia.ui.form.field.definition.migration.HiddenFieldDefinitionConverter;
75  import info.magnolia.ui.form.field.definition.migration.LinkFieldDefinitionConverter;
76  import info.magnolia.ui.form.field.definition.migration.MultiValueFieldDefinitionConverter;
77  import info.magnolia.ui.form.field.definition.migration.OptionGroupFieldDefinitionConverter;
78  import info.magnolia.ui.form.field.definition.migration.RichTextFieldDefinitionConverter;
79  import info.magnolia.ui.form.field.definition.migration.SelectFieldDefinitionConverter;
80  import info.magnolia.ui.form.field.definition.migration.StaticFieldDefinitionConverter;
81  import info.magnolia.ui.form.field.definition.migration.SwitchableFieldDefinitionConverter;
82  import info.magnolia.ui.form.field.definition.migration.TextFieldDefinitionConverter;
83  import info.magnolia.ui.form.field.definition.migration.TwinColSelectFieldDefinitionConverter;
84  import info.magnolia.ui.form.field.definition.migration.BasicUploadFieldDefinitionConverter;
85  import info.magnolia.ui.framework.layout.ConfiguredTabDefinition;
86  import info.magnolia.ui.framework.layout.TabDefinition;
87  import info.magnolia.ui.framework.layout.TabbedLayoutDefinition;
88  
89  import java.util.HashMap;
90  import java.util.HashSet;
91  import java.util.List;
92  import java.util.Map;
93  import java.util.Optional;
94  import java.util.Set;
95  import java.util.stream.Collectors;
96  
97  import org.slf4j.Logger;
98  import org.slf4j.LoggerFactory;
99  
100 import net.sf.cglib.proxy.Enhancer;
101 
102 /**
103  * Functional interface for definition converters.
104  *
105  * @param <OLD> - old definition class
106  * @param <NEW> - new definition class
107  */
108 @FunctionalInterface
109 public interface DefinitionConverter<OLD, NEW> {
110 
111     Logger log = LoggerFactory.getLogger(DefinitionConverter.class);
112 
113     NEW convert(OLD definition);
114 
115     Map<Class<? extends info.magnolia.ui.form.field.definition.FieldDefinition>, FieldDefinitionConverter> FIELD_DEFINITION_CONVERTERS = new HashMap<Class<? extends info.magnolia.ui.form.field.definition.FieldDefinition>, FieldDefinitionConverter>() {{
116         put(TextFieldDefinition.class, new TextFieldDefinitionConverter());
117         put(StaticFieldDefinition.class, new StaticFieldDefinitionConverter());
118         put(HiddenFieldDefinition.class, new HiddenFieldDefinitionConverter());
119         put(CodeFieldDefinition.class, new CodeFieldDefinitionConverter());
120         put(BasicTextCodeFieldDefinition.class, new CodeFieldDefinitionConverter());
121         put(CheckboxFieldDefinition.class, new CheckboxFieldDefinitionConverter());
122         put(RichTextFieldDefinition.class, new RichTextFieldDefinitionConverter());
123         put(DateFieldDefinition.class, new DateFieldDefinitionConverter());
124         put(LinkFieldDefinition.class, new LinkFieldDefinitionConverter());
125         put(SelectFieldDefinition.class, new SelectFieldDefinitionConverter());
126         put(OptionGroupFieldDefinition.class, new OptionGroupFieldDefinitionConverter());
127         put(TwinColSelectFieldDefinition.class, new TwinColSelectFieldDefinitionConverter());
128         put(BasicUploadFieldDefinition.class, new BasicUploadFieldDefinitionConverter());
129         put(SwitchableFieldDefinition.class, new SwitchableFieldDefinitionConverter());
130         put(CompositeFieldDefinition.class, new CompositeFieldDefinitionConverter());
131         put(MultiValueFieldDefinition.class, new MultiValueFieldDefinitionConverter());
132     }};
133 
134     DefinitionConverter<info.magnolia.ui.form.field.definition.FieldDefinition, NamedFieldDefinition> NAMED = (oldDefinition) -> {
135         ConfiguredNamedFieldDefinition namedDefinition = new ConfiguredNamedFieldDefinition();
136         namedDefinition.setName(oldDefinition instanceof BasicUploadFieldDefinition ?
137                 ((BasicUploadFieldDefinition) oldDefinition).getBinaryNodeName() :
138                 oldDefinition.getName());
139         return namedDefinition;
140     };
141 
142     DefinitionConverter<info.magnolia.ui.form.definition.TabDefinition, TabDefinition> TAB = (oldDefinition) -> {
143         ConfiguredTabDefinitioninition.html#ConfiguredTabDefinition">ConfiguredTabDefinition newDefinition = new ConfiguredTabDefinition();
144         newDefinition.setLabel(oldDefinition.getLabel());
145         newDefinition.setName(oldDefinition.getName());
146         newDefinition.setFields(oldDefinition.getFields().stream().map(NAMED::convert).collect(Collectors.toList()));
147         return newDefinition;
148     };
149 
150     DefinitionConverter<info.magnolia.ui.form.field.definition.FieldDefinition, EditorPropertyDefinition> FIELD = (oldDefinition) -> {
151         log.debug("Converting old framework field definition [{}] to new definition.", oldDefinition.getName());
152 
153         Class oldDefinitionClass = Enhancer.isEnhanced(oldDefinition.getClass()) || MagnoliaProxy.class.isAssignableFrom(oldDefinition.getClass())
154                 ? oldDefinition.getClass().getSuperclass() : oldDefinition.getClass();
155         FieldDefinitionConverter converter = Optional.of(oldDefinitionClass)
156                 .map(FIELD_DEFINITION_CONVERTERS::get)
157                 .filter(selectedConverter -> selectedConverter.supports(oldDefinition))
158                 .orElse(new FallbackFieldDefinitionConverter());
159         return converter.convert(oldDefinition);
160     };
161 
162     DefinitionConverter<info.magnolia.ui.form.definition.FormDefinition, FormDefinition> FORM = (oldDefinition) -> {
163         TabbedLayoutDefinition tabbedLayoutDefinition = new TabbedLayoutDefinition();
164         tabbedLayoutDefinition.setTabs(oldDefinition.getTabs().stream().map(TAB::convert).collect(Collectors.toList()));
165         ConfiguredFormDefinition<?> newDefinition = new ConfiguredFormDefinition<>();
166         newDefinition.setName(oldDefinition.getLabel());
167         newDefinition.setLayout(tabbedLayoutDefinition);
168         //newDefinition.setImplementationClass();
169         final Set<String> fieldNames = new HashSet<>();
170         List<EditorPropertyDefinition> properties = oldDefinition
171                 .getTabs()
172                 .stream()
173                 .map(info.magnolia.ui.form.definition.TabDefinition::getFields)
174                 .flatMap(List::stream)
175                 .map(FIELD::convert)
176                 .filter(field -> {
177                     if (fieldNames.contains(field.getName())) {
178                         // old form definitions could have more than one (static) fields of the same name on different tabs
179                         log.warn("Removing field with non-unique name: " + field.getName());
180                         return false;
181                     }
182                     fieldNames.add(field.getName());
183                     return true;
184                 })
185                 .collect(Collectors.toList());
186 
187         newDefinition.setProperties(properties);
188         return newDefinition;
189     };
190 
191     DefinitionConverter<ActionDefinition, ActionDefinition> ACTION = (oldDefinition) -> {
192         log.debug("Converting old framework action definition [{}] to new definition.", oldDefinition.getName());
193         if (oldDefinition instanceof SaveFormActionDefinition || oldDefinition instanceof SaveDialogActionDefinition) {
194             return new CommitActionDefinition();
195         } else if (oldDefinition instanceof CancelDialogActionDefinition || oldDefinition instanceof CancelFormActionDefinition) {
196             return new CloseActionDefinition();
197         } else {
198             final ConfiguredActionDefinition configuredActionDefinition = new ConfiguredActionDefinition();
199             configuredActionDefinition.setName("Unsupported action");
200             configuredActionDefinition.setDescription("Please migrate to new framework dialog");
201             return configuredActionDefinition;
202         }
203     };
204 
205     DefinitionConverter<info.magnolia.ui.dialog.definition.FormDialogDefinition, DialogDefinition> DIALOG = (oldDefinition) -> {
206         log.debug("Converting old framework dialog definition [{}] to new definition.",oldDefinition.getId());
207         ConfiguredFormDialogDefinition<Object> newDefinition = new ConfiguredFormDialogDefinition<>();
208         final FormDefinition<Object> convert = FORM.convert(oldDefinition.getForm());
209         newDefinition.setLabel(oldDefinition.getLabel());
210         newDefinition.setId(oldDefinition.getId());
211         newDefinition.setLight(oldDefinition.isLight());
212         newDefinition.setForm(convert);
213         newDefinition.setActions(oldDefinition.getActions().entrySet().stream()
214                 .collect(Collectors.toMap(Map.Entry::getKey, entry -> ACTION.convert(entry.getValue())))
215         );
216         return newDefinition;
217     };
218 }