View Javadoc
1   /**
2    * This file Copyright (c) 2010-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.commands;
35  
36  
37  import info.magnolia.commands.chain.Catalog;
38  import info.magnolia.commands.chain.Chain;
39  import info.magnolia.commands.chain.ChainBase;
40  import info.magnolia.commands.chain.Command;
41  import info.magnolia.jcr.node2bean.Node2BeanException;
42  import info.magnolia.jcr.node2bean.PropertyTypeDescriptor;
43  import info.magnolia.jcr.node2bean.TransformationState;
44  import info.magnolia.jcr.node2bean.TypeDescriptor;
45  import info.magnolia.jcr.node2bean.TypeMapping;
46  import info.magnolia.jcr.node2bean.impl.Node2BeanTransformerImpl;
47  import info.magnolia.objectfactory.Classes;
48  import info.magnolia.objectfactory.ComponentProvider;
49  
50  import java.util.Iterator;
51  import java.util.Map;
52  
53  import javax.jcr.Node;
54  import javax.jcr.RepositoryException;
55  
56  import org.apache.commons.lang3.StringUtils;
57  
58  /**
59   * Command to transform old "impl" reference to implementing class to new "class" node data name for references.
60   */
61  public class CommandTransformer extends Node2BeanTransformerImpl {
62      private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CommandTransformer.class);
63  
64      private static final String DEPRECATED_CATALOG_NAME_NODE_DATA = "catalogName";
65  
66      private static final String DEPRECATED_IMPL_NODE_DATA = "impl";
67  
68      @Override
69      protected TypeDescriptorcriptor">TypeDescriptor onResolveType(TypeMapping typeMapping, TransformationState state, TypeDescriptor resolvedType, ComponentProvider componentProvider) {
70          if (resolvedType != null) {
71              return resolvedType;
72          }
73          Class klass = null;
74          // default class to use
75          if (state.getLevel() == 1) {
76              klass = MgnlCatalog.class;
77          } else {
78              Node node = state.getCurrentNode();
79              try {
80                  if (node.hasProperty(DEPRECATED_IMPL_NODE_DATA)) {
81                      log.warn("Rename  '" + DEPRECATED_IMPL_NODE_DATA + "' to 'class' [{}]!", node);
82                      try {
83                          final String className = node.getProperty(DEPRECATED_IMPL_NODE_DATA).getString();
84                          klass = Classes.getClassFactory().forName(className);
85                      } catch (ClassNotFoundException e) {
86                          klass = DelegateCommand.class;
87                      }
88                  } else {
89                      // In case we are not yet building a concreate command we are creating a chain.
90                      // Otherwise we are building command properties
91                      boolean buildingCommand = false;
92                      for (int i = 0; i < state.getLevel() - 1; i++) {
93                          TypeDescriptor td = state.peekType(i);
94                          if (isCommandClass(td.getType()) && !isChainClass(td.getType())) {
95                              buildingCommand = true;
96                          }
97                      }
98                      if (!buildingCommand) {
99                          klass = ChainBase.class;
100                     }
101                 }
102             } catch (RepositoryException e) {
103                 log.error("Can't check " + DEPRECATED_IMPL_NODE_DATA + " nodedata [{}]", node, e);
104             }
105         }
106         if (klass != null) {
107             return typeMapping.getTypeDescriptor(klass);
108         }
109         return resolvedType;
110     }
111 
112     @Override
113     public void initBean(TransformationState state, Map values) throws Node2BeanException {
114         // we add the commands here (reflection does not work)
115         if (state.getCurrentBean() instanceof Catalog) {
116             Catalog/../../info/magnolia/commands/chain/Catalog.html#Catalog">Catalog catalog = (Catalog) state.getCurrentBean();
117             for (Iterator iter = values.keySet().iterator(); iter.hasNext(); ) {
118                 String name = (String) iter.next();
119                 if (values.get(name) instanceof Command) {
120                     Command/../../info/magnolia/commands/chain/Command.html#Command">Command command = (Command) values.get(name);
121                     if (!(command instanceof MgnlCommand./../../info/magnolia/commands/MgnlCommand.html#MgnlCommand">MgnlCommand) || ((MgnlCommand) command).isEnabled()) {
122                         catalog.addCommand(name, command);
123                     }
124                 }
125             }
126         }
127 
128         // support chains
129         if (state.getCurrentBean() instanceof Chain) {
130             Chain="../../../info/magnolia/commands/chain/Chain.html#Chain">Chain chain = (Chain) state.getCurrentBean();
131             for (Iterator iter = values.values().iterator(); iter.hasNext(); ) {
132                 Object value = iter.next();
133                 if (value instanceof Command) {
134                     Command/../../info/magnolia/commands/chain/Command.html#Command">Command command = (Command) value;
135                     if (!(command instanceof MgnlCommand./../../info/magnolia/commands/MgnlCommand.html#MgnlCommand">MgnlCommand) || ((MgnlCommand) command).isEnabled()) {
136                         chain.addCommand(command);
137                     }
138                 }
139             }
140         }
141 
142         // support old way (using impl) of configuring delegate commands
143         if (state.getCurrentBean() instanceof DelegateCommand) {
144             DelegateCommandolia/commands/DelegateCommand.html#DelegateCommand">DelegateCommand delegateCommand = (DelegateCommand) state.getCurrentBean();
145             if (StringUtils.isEmpty(delegateCommand.getCommandName())) {
146                 log.warn("You should define the commandName property on [{}]", state.getCurrentNode());
147                 delegateCommand.setCommandName((String) values.get(DEPRECATED_IMPL_NODE_DATA));
148             }
149         }
150         super.initBean(state, values);
151     }
152 
153     @Override
154     public void setProperty(TypeMapping typeMapping, TransformationState state, PropertyTypeDescriptor descriptor, Map values) throws RepositoryException {
155         Object bean = state.getCurrentBean();
156         if (bean instanceof MgnlCatalog) {
157             MgnlCatalog../info/magnolia/commands/MgnlCatalog.html#MgnlCatalog">MgnlCatalog catalog = (MgnlCatalog) bean;
158             if (values.containsKey(DEPRECATED_CATALOG_NAME_NODE_DATA)) {
159                 log.warn("Rename the 'catalogName' nodedata to 'name' [{}]", state.getCurrentNode());
160                 catalog.setName((String) values.get(DEPRECATED_CATALOG_NAME_NODE_DATA));
161             }
162 
163             if (!values.containsKey("name") && state.getCurrentNode().getName().equals("commands")) {
164                 try {
165                     catalog.setName(state.getCurrentNode().getParent().getName());
166                 } catch (RepositoryException e) {
167                     log.error("Can't resolve catalog name by using parent node [{}]", state.getCurrentNode(), e);
168                 }
169             }
170         }
171 
172         super.setProperty(typeMapping, state, descriptor, values);
173     }
174 
175     protected boolean isCommandClass(Class<?> type) {
176         return Command.class.isAssignableFrom(type);
177     }
178 
179     protected boolean isChainClass(Class<?> type) {
180         return Chain.class.isAssignableFrom(type);
181     }
182 }