View Javadoc

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