View Javadoc

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