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