Coverage Report - org.kuali.student.common.dictionary.service.impl.old.DictionaryBeanDefinitionParser
 
Classes in this File Line Coverage Branch Coverage Complexity
DictionaryBeanDefinitionParser
87%
117/133
84%
118/140
11.889
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.common.dictionary.service.impl.old;
 17  
 
 18  
 import java.text.SimpleDateFormat;
 19  
 import java.util.HashMap;
 20  
 import java.util.HashSet;
 21  
 import java.util.List;
 22  
 import java.util.Map;
 23  
 
 24  
 import javax.xml.parsers.DocumentBuilder;
 25  
 import javax.xml.parsers.DocumentBuilderFactory;
 26  
 
 27  
 import org.apache.log4j.Logger;
 28  
 import org.kuali.student.common.dictionary.old.dto.CaseConstraint;
 29  
 import org.kuali.student.common.dictionary.old.dto.ConstraintDescriptor;
 30  
 import org.kuali.student.common.dictionary.old.dto.ConstraintSelector;
 31  
 import org.kuali.student.common.dictionary.old.dto.Context;
 32  
 import org.kuali.student.common.dictionary.old.dto.Field;
 33  
 import org.kuali.student.common.dictionary.old.dto.FieldDescriptor;
 34  
 import org.kuali.student.common.dictionary.old.dto.LookupConstraint;
 35  
 import org.kuali.student.common.dictionary.old.dto.LookupKeyConstraint;
 36  
 import org.kuali.student.common.dictionary.old.dto.ObjectStructure;
 37  
 import org.kuali.student.common.dictionary.old.dto.OccursConstraint;
 38  
 import org.kuali.student.common.dictionary.old.dto.RequireConstraint;
 39  
 import org.kuali.student.common.dictionary.old.dto.SearchSelector;
 40  
 import org.kuali.student.common.dictionary.old.dto.State;
 41  
 import org.kuali.student.common.dictionary.old.dto.Type;
 42  
 import org.kuali.student.common.dictionary.old.dto.TypeStateCaseConstraint;
 43  
 import org.kuali.student.common.dictionary.old.dto.TypeStateWhenConstraint;
 44  
 import org.kuali.student.common.dictionary.old.dto.ValidCharsConstraint;
 45  
 import org.kuali.student.common.dictionary.old.dto.WhenConstraint;
 46  
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 47  
 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 48  
 import org.springframework.beans.factory.xml.ParserContext;
 49  
 import org.w3c.dom.Attr;
 50  
 import org.w3c.dom.Document;
 51  
 import org.w3c.dom.Element;
 52  
 import org.w3c.dom.Node;
 53  
 
 54  
 /**
 55  
  * @author Daniel Epstein
 56  
  *
 57  
  */
 58  
 @Deprecated
 59  6
 public class DictionaryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser{
 60  
     
 61  6
     final Logger logger = Logger.getLogger(DictionaryBeanDefinitionParser.class);
 62  
 
 63  
         //Resolves the tag name to an actual class
 64  
     @Override
 65  
     protected Class<?> getBeanClass(Element element) {
 66  
 
 67  4695
             if (element.getLocalName().equals("case")){
 68  0
                     return CaseConstraint.class;
 69  
                 }
 70  4695
                 if (element.getLocalName().equals("constraintDescriptor")) {
 71  993
                         return ConstraintDescriptor.class;
 72  
                 }
 73  3702
                 if (element.getLocalName().equals("constraint")) {
 74  263
                         return ConstraintSelector.class;
 75  
                 }
 76  3439
                 if (element.getLocalName().equals("context")) {
 77  0
                         return Context.class;
 78  
                 }
 79  3439
                 if (element.getLocalName().equals("field")) {
 80  993
                         return Field.class;
 81  
                 }
 82  2446
                 if (element.getLocalName().equals("fieldDescriptor")) {
 83  992
                         return FieldDescriptor.class;
 84  
                 }
 85  1454
                 if (element.getLocalName().equals("lookup")) {
 86  55
                         return LookupConstraint.class;
 87  
                 }
 88  1399
                 if (element.getLocalName().equals("lookupKey")) {
 89  55
                         return LookupKeyConstraint.class;
 90  
                 }
 91  1344
                 if (element.getLocalName().equals("objectStructure")) {
 92  322
                         return ObjectStructure.class;
 93  
                 }
 94  1022
                 if (element.getLocalName().equals("occurs")) {
 95  0
                         return OccursConstraint.class;
 96  
                 }
 97  1022
                 if (element.getLocalName().equals("require")) {
 98  0
                         return RequireConstraint.class;
 99  
                 }
 100  1022
                 if (element.getLocalName().equals("search")) {
 101  0
                         return SearchSelector.class;
 102  
                 }
 103  1022
                 if (element.getLocalName().equals("state")) {
 104  573
                         return State.class;
 105  
                 }
 106  449
                 if (element.getLocalName().equals("type")) {
 107  361
                         return Type.class;
 108  
                 }
 109  88
                 if (element.getLocalName().equals("typeStateCase")) {
 110  4
                         return TypeStateCaseConstraint.class;
 111  
                 }
 112  84
                 if (element.getLocalName().equals("typeStateWhen")) {
 113  6
                         return TypeStateWhenConstraint.class;
 114  
                 }
 115  78
                 if (element.getLocalName().equals("when")) {
 116  0
                         return WhenConstraint.class;
 117  
                 }
 118  78
                 if (element.getLocalName().equals("validChars")) {
 119  78
                         return ValidCharsConstraint.class;
 120  
                 }
 121  
             
 122  
 
 123  0
         return super.getBeanClass(element);
 124  
     }
 125  
 
 126  
     @Override
 127  
     protected void doParse(Element element, ParserContext pc, BeanDefinitionBuilder builder) {
 128  
           
 129  
             //Copy Attributes
 130  4695
             if(element.hasAttributes()){
 131  8209
                     for(int i = 0;i<element.getAttributes().getLength();i++){
 132  5149
                         Attr attr = (Attr) element.getAttributes().item(i);
 133  5149
                         if("abstract".equals(attr.getName())){
 134  400
                                 builder.setAbstract(true);
 135  4749
                         }else if(!"id".equals(attr.getName())&&!"parent".equals(attr.getName())){
 136  2763
                                 builder.addPropertyValue(attr.getName(), attr.getValue());
 137  
                         }
 138  
                     }
 139  
             }
 140  
             
 141  
             //Parse the children
 142  4695
             HashSet<String> visitedNodes = new HashSet<String>();
 143  52631
         for(int i = 0;i<element.getChildNodes().getLength();i++){
 144  47936
             Node node = element.getChildNodes().item(i);
 145  
 
 146  
             //We are only interested in child elements that have not been visited
 147  47936
             if(Node.ELEMENT_NODE == node.getNodeType()){                      
 148  
                     
 149  
                     //Get the local name minus the "Ref"
 150  19738
                     String localName=node.getLocalName();
 151  19738
                     if(localName.endsWith("Ref")){
 152  12815
                             localName=localName.substring(0, localName.length()-"Ref".length());
 153  
                     }
 154  19738
                     if(!visitedNodes.contains(localName)){
 155  
                             //Check if the child element belongs in a list
 156  7533
                             if(isList(localName)){
 157  2172
                                     Element childList=getChildList(element,localName);
 158  2172
                                 visitedNodes.add(localName);
 159  2172
                             List<?> refList = pc.getDelegate().parseListElement(childList, pc.getContainingBeanDefinition());
 160  2172
                             if(refList!=null&&!refList.isEmpty()){
 161  2172
                                     String fieldName=resolveFieldName(element.getLocalName(),localName);
 162  2172
                                     builder.addPropertyValue(fieldName,refList);
 163  
                             }
 164  
                         //Check if this is an attribute map
 165  2172
                             }else if("attributes".equals(node.getLocalName())){
 166  2
                                     Map<String,String> attributes = getAttributeMap((Element)node);
 167  2
                                     builder.addPropertyValue(node.getLocalName(), attributes);
 168  
                         //Check if the child element is a Ref
 169  2
                         }else if(node.getLocalName().endsWith("Ref")){
 170  221
                                 if("objectStructureRef".equals(node.getLocalName())){
 171  5
                                         builder.addPropertyValue("objectStructureRef", ((Element)node).getAttribute("bean"));
 172  
                                         //Add in the nested object too
 173  5
                                         builder.addPropertyReference("objectStructure", ((Element)node).getAttribute("bean"));
 174  
                                 }else{
 175  216
                                         builder.addPropertyReference(localName, ((Element)node).getAttribute("bean"));
 176  
                                 }
 177  
                        }else{
 178  
                                 //Get the child of the child to see if we need to parse the nested node, or just set the text value
 179  5138
                             Element childElement = getFirstChildElement(node);
 180  5138
                             if(childElement!=null ||"search".equals(node.getLocalName())){
 181  
                                     //Parse the nested Node
 182  1901
                                 Object childBean = pc.getDelegate().parsePropertySubElement((Element)node, pc.getContainingBeanDefinition());
 183  1901
                                 String fieldName=resolveFieldName(element.getLocalName(),node.getLocalName());
 184  1901
                                 builder.addPropertyValue(fieldName, childBean);
 185  1901
                             }else{
 186  
                                     
 187  
                                     
 188  
                                            //Set the text value
 189  3237
                                         String fieldName=resolveFieldName(element.getLocalName(),node.getLocalName());
 190  
 
 191  3237
                                         if(Node.ELEMENT_NODE == node.getNodeType()&&"date".equals(((Element)node).getSchemaTypeInfo().getTypeName())){
 192  4
                                                 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
 193  
                                                 try {
 194  4
                                                                         builder.addPropertyValue(fieldName, df.parse(node.getTextContent()));
 195  0
                                                                 } catch (Exception e) {
 196  0
                                                                         logger.error("Cannot convert date, must be in format 'YYYY-MM-DD' :"+node.getTextContent(),e);
 197  4
                                                                 }
 198  4
                                         }else{
 199  3233
                                                 builder.addPropertyValue(fieldName, node.getTextContent());
 200  
                                         }
 201  
                             }
 202  
                         }
 203  
                     }
 204  
                 }
 205  
         }
 206  4695
     }
 207  
 
 208  
     
 209  
     /**
 210  
      * Parses attribute map from 
 211  
      * &lt;attributes&gt;
 212  
      *         &lt;attribute key="attr1" value="attr2"/&gt;
 213  
      * &lt;/attributes&gt;
 214  
      * @param element
 215  
      * @return map of attributes
 216  
      */
 217  
     private Map<String, String> getAttributeMap(Element element) {
 218  2
             Map<String, String> attributes = new HashMap<String, String>();
 219  12
             for(int i = 0;i<element.getChildNodes().getLength();i++){
 220  10
                     Node node = element.getChildNodes().item(i);
 221  10
                     if(Node.ELEMENT_NODE == node.getNodeType() && "attribute".equals(node.getLocalName())){
 222  4
                             String key = ((Element)node).getAttribute("key");
 223  4
                             String value = ((Element)node).getAttribute("value");
 224  4
                             attributes.put(key, value);
 225  
                     }
 226  
             }
 227  2
                 return attributes;
 228  
         }
 229  
 
 230  
         //This builds up a list of the child nodes so that the spring parseListElement can be used
 231  
     //it also translates <fooRef> elements into straight spring <ref> elements
 232  
     private Element getChildList(Element element, String localName) {
 233  
             try{
 234  
                     //Create a new document to contain our list of elements
 235  2172
                     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 236  2172
                     DocumentBuilder builder = dbf.newDocumentBuilder();
 237  2172
                     Document doc = builder.newDocument();
 238  
         
 239  2172
                     Element root = doc.createElement("listRoot");
 240  
                     
 241  36736
                 for(int i = 0;i<element.getChildNodes().getLength();i++){
 242  34564
                     Node node = element.getChildNodes().item(i);
 243  34564
                     if(Node.ELEMENT_NODE == node.getNodeType() && localName.equals(node.getLocalName())){
 244  
                             
 245  
                             //Copy the node from the spring config to our list
 246  1783
                             Node copied = doc.importNode(node, true);
 247  1783
                             root.appendChild(copied);
 248  
                     }
 249  34564
                     if(Node.ELEMENT_NODE == node.getNodeType() && (localName+"Ref").equals(node.getLocalName())){
 250  
                             
 251  
                             //Create a new spring ref element and copy the bean attribute
 252  12594
                             Element ref = doc.createElement("ref");
 253  12594
                             ref.setAttribute("bean", ((Element)node).getAttribute("bean"));
 254  12594
                             root.appendChild(ref);
 255  
                     }
 256  
                 }
 257  
                 
 258  2172
                     return root;
 259  0
             }catch(Exception e){
 260  0
                     logger.error("Exception occured: ", e);
 261  
             }
 262  0
             return null;
 263  
         }
 264  
 
 265  
     //This is called to resolve tag names to field names based on the element and parent element local names
 266  
         private String resolveFieldName(String parentName, String nodeName) {
 267  7310
                 if("constraint".equals(parentName)&&"case".equals(nodeName)){
 268  0
                         return "caseConstraint";
 269  
                 }
 270  7310
                 if("constraint".equals(parentName)&&"typeStateCase".equals(nodeName)){
 271  4
                         return "typeStateCaseConstraint";
 272  
                 }
 273  7306
                 if("constraint".equals(parentName)&&"lookup".equals(nodeName)){
 274  55
                         return "lookupConstraint";
 275  
                 }
 276  7251
                 if("constraint".equals(parentName)&&"occurs".equals(nodeName)){
 277  0
                         return "occursConstraint";
 278  
                 }
 279  7251
                 if("constraint".equals(parentName)&&"require".equals(nodeName)){
 280  0
                         return "requireConstraint";
 281  
                 }
 282  7251
                 if("case".equals(parentName)&&"when".equals(nodeName)){
 283  0
                         return "whenConstraint";
 284  
                 }
 285  
 
 286  7251
                 return nodeName;
 287  
         }
 288  
 
 289  
         //Gets the first child element
 290  
         private Element getFirstChildElement(Node node) {
 291  10808
         for(int i = 0;i<node.getChildNodes().getLength();i++){
 292  7571
             Node childNode = node.getChildNodes().item(i);
 293  7571
             if(Node.ELEMENT_NODE == childNode.getNodeType()){
 294  1901
                 return (Element) childNode;
 295  
             }
 296  
         }
 297  3237
         return null;
 298  
     }
 299  
 
 300  
         //Returns true if the element should be part of a list
 301  
     private boolean isList(String localName) {
 302  
 
 303  7533
         return "field".equals(localName)||
 304  
                    "case".equals(localName)||
 305  
                    "when".equals(localName)||
 306  
                    "lookup".equals(localName)||
 307  
                    "lookupKey".equals(localName)||
 308  
                    "occurs".equals(localName)||
 309  
                    "constraint".equals(localName)||
 310  
                    "type".equals(localName)||
 311  
                    "state".equals(localName)||
 312  
                    "require".equals(localName);
 313  
     }
 314  
 
 315  
     //This makes use of the spring parent="" functionality 
 316  
         @Override
 317  
         protected String getParentName(Element element) {
 318  4695
                 if(element.hasAttribute("parent")){
 319  403
             return element.getAttribute("parent");
 320  
                 }
 321  4292
                 return super.getParentName(element);
 322  
         }
 323  
 
 324  
         //This means any bean without an id attribute gets one auto generated for it
 325  
         @Override
 326  
         protected boolean shouldGenerateIdAsFallback() {
 327  3112
                 return true;
 328  
         }
 329  
         
 330  
 }