Coverage Report - org.kuali.student.common.search.service.impl.SearchBeanDefinitionParser
 
Classes in this File Line Coverage Branch Coverage Complexity
SearchBeanDefinitionParser
79%
93/117
72%
86/118
9.778
 
 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.search.service.impl;
 17  
 
 18  
 import java.util.HashSet;
 19  
 import java.util.List;
 20  
 
 21  
 import javax.xml.parsers.DocumentBuilder;
 22  
 import javax.xml.parsers.DocumentBuilderFactory;
 23  
 
 24  
 import org.apache.log4j.Logger;
 25  
 import org.kuali.student.common.dictionary.old.dto.FieldDescriptor;
 26  
 import org.kuali.student.common.search.dto.ComparisonParamInfo;
 27  
 import org.kuali.student.common.search.dto.CrossSearchTypeInfo;
 28  
 import org.kuali.student.common.search.dto.JoinComparisonInfo;
 29  
 import org.kuali.student.common.search.dto.JoinCriteriaInfo;
 30  
 import org.kuali.student.common.search.dto.JoinResultMappingInfo;
 31  
 import org.kuali.student.common.search.dto.QueryParamInfo;
 32  
 import org.kuali.student.common.search.dto.ResultColumnInfo;
 33  
 import org.kuali.student.common.search.dto.SearchCriteriaTypeInfo;
 34  
 import org.kuali.student.common.search.dto.SearchResultTypeInfo;
 35  
 import org.kuali.student.common.search.dto.SearchTypeInfo;
 36  
 import org.kuali.student.common.search.dto.SubSearchInfo;
 37  
 import org.kuali.student.common.search.dto.SubSearchParamMappingInfo;
 38  
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 39  
 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 40  
 import org.springframework.beans.factory.xml.ParserContext;
 41  
 import org.w3c.dom.Attr;
 42  
 import org.w3c.dom.Document;
 43  
 import org.w3c.dom.Element;
 44  
 import org.w3c.dom.Node;
 45  
 
 46  2
 public class SearchBeanDefinitionParser extends
 47  
                 AbstractSingleBeanDefinitionParser {
 48  1
     private static final Logger logger = Logger.getLogger(SearchBeanDefinitionParser.class);
 49  
 
 50  
         @Override
 51  
         protected Class<?> getBeanClass(Element element) {
 52  
 
 53  44
                 if (element.getLocalName().equals("fieldDescriptor")) {
 54  0
                         return FieldDescriptor.class;
 55  
                 }
 56  44
                 if (element.getLocalName().equals("searchCriteriaTypeInfo")) {
 57  6
                         return SearchCriteriaTypeInfo.class;
 58  
                 }
 59  38
                 if (element.getLocalName().equals("queryParam")) {
 60  0
                         return QueryParamInfo.class;
 61  
                 }
 62  38
                 if (element.getLocalName().equals("searchType")) {
 63  4
                         return SearchTypeInfo.class;
 64  
                 }
 65  34
                 if (element.getLocalName().equals("resultColumn")) {
 66  12
                         return ResultColumnInfo.class;
 67  
                 }
 68  22
                 if (element.getLocalName().equals("searchResultTypeInfo")) {
 69  6
                         return SearchResultTypeInfo.class;
 70  
                 }
 71  
                 
 72  
                 
 73  16
                 if (element.getLocalName().equals("crossSearchType")) {
 74  2
                         return CrossSearchTypeInfo.class;
 75  
                 }
 76  14
                 if (element.getLocalName().equals("subSearch")) {
 77  4
                         return SubSearchInfo.class;
 78  
                 }
 79  10
                 if (element.getLocalName().equals("subSearchParamMappings")) {
 80  0
                         return SubSearchParamMappingInfo.class;
 81  
                 }
 82  10
                 if (element.getLocalName().equals("joinCriteria")) {
 83  2
                         return JoinCriteriaInfo.class;
 84  
                 }
 85  8
                 if (element.getLocalName().equals("comparison")) {
 86  0
                         return JoinComparisonInfo.class;
 87  
                 }
 88  8
                 if (element.getLocalName().equals("leftHandSide")) {
 89  0
                         return ComparisonParamInfo.class;
 90  
                 }
 91  8
                 if (element.getLocalName().equals("rightHandSide")) {
 92  0
                         return ComparisonParamInfo.class;
 93  
                 }
 94  8
                 if (element.getLocalName().equals("joinResultMapping")) {
 95  8
                         return JoinResultMappingInfo.class;
 96  
                 }
 97  
 
 98  0
                 return super.getBeanClass(element);
 99  
         }
 100  
 
 101  
         @Override
 102  
         protected void doParse(Element element, ParserContext pc, BeanDefinitionBuilder builder) {
 103  
                 //Set the key
 104  44
                 if(!"fieldDescriptor".equals(element.getLocalName())&&element.hasAttribute("id")){
 105  6
                         builder.addPropertyValue("key", element.getAttributes().getNamedItem("id").getTextContent());
 106  
                 }
 107  
                 
 108  44
                 if("fieldDescriptor".equals(element.getLocalName())&&element.hasAttribute("parent")){
 109  0
                         builder.setParentName(element.getAttributes().getNamedItem("parent").getTextContent());
 110  
                 }
 111  
                 
 112  
                 //Set optional if its a queryParam
 113  44
                 if("queryParam".equals(element.getLocalName())&&element.hasAttribute("optional")){
 114  0
                         builder.addPropertyValue("optional", "true".equals(element.getAttribute("optional"))?true:false);
 115  
                 }
 116  
                 
 117  
             //Copy Attributes
 118  44
             if(element.hasAttributes()){
 119  60
                     for(int i = 0;i<element.getAttributes().getLength();i++){
 120  40
                         Attr attr = (Attr) element.getAttributes().item(i);
 121  40
                         if("abstract".equals(attr.getName())){
 122  0
                                 builder.setAbstract(true);
 123  40
                         }else if(!"id".equals(attr.getName())&&!"parent".equals(attr.getName())){
 124  34
                                 String fieldName = resolveFieldName(element.getLocalName(),attr.getName());
 125  34
                                 builder.addPropertyValue(fieldName, attr.getValue());
 126  
                         }
 127  
                     }
 128  
             }
 129  
                 
 130  
         
 131  44
                 HashSet<String> visitedNodes = new HashSet<String>();
 132  
                 //Parse the children
 133  268
                 for(int i = 0;i<element.getChildNodes().getLength();i++){
 134  224
                         Node node = element.getChildNodes().item(i);
 135  
 
 136  224
                         if(Node.ELEMENT_NODE == node.getNodeType()){
 137  94
                     String localName=node.getLocalName();
 138  94
                     if(!visitedNodes.contains(localName)){
 139  86
                                         if(isWrappedList(node.getLocalName())){
 140  12
                                                 List<?> refList = pc.getDelegate().parseListElement((Element) node, pc.getContainingBeanDefinition());
 141  12
                                                 builder.addPropertyValue(node.getLocalName(),refList);
 142  12
                                         }else if(isUnwrappedList(node.getLocalName())){
 143  4
                                     Element childList=getChildList(element,node.getLocalName());
 144  4
                                 visitedNodes.add(node.getLocalName());
 145  4
                             List<?> refList = pc.getDelegate().parseListElement(childList, pc.getContainingBeanDefinition());
 146  4
                             if(refList!=null&&!refList.isEmpty()){
 147  4
                                     String fieldName=resolveFieldName(element.getLocalName(),node.getLocalName());
 148  4
                                     builder.addPropertyValue(fieldName,refList);
 149  
                             }
 150  4
                                         }else{
 151  70
                                                 Element childElement = getFirstChildElement(node); 
 152  70
                                                 if(childElement!=null){
 153  12
                                                         if("ref".equals(childElement.getLocalName())){
 154  0
                                                                 Object childBean = pc.getDelegate().parsePropertySubElement(childElement, pc.getContainingBeanDefinition());
 155  0
                                                                 builder.addPropertyValue(node.getLocalName(), childBean);
 156  0
                                                         }else{
 157  12
                                                                 Object childBean = pc.getDelegate().parsePropertySubElement((Element)node, pc.getContainingBeanDefinition());
 158  12
                                                                 builder.addPropertyValue(node.getLocalName(), childBean);
 159  12
                                                         }
 160  
                                                 }else{
 161  58
                                                         if(("ref".equals(node.getLocalName())&&"queryParam".equals(element.getLocalName()))){
 162  0
                                                                 Object childBean = pc.getDelegate().parsePropertySubElement((Element)node, pc.getContainingBeanDefinition());
 163  0
                                                                 builder.addPropertyValue("fieldDescriptor", childBean);
 164  0
                                                         }else if("leftHandSide".equals(node.getLocalName())
 165  
                                                                         ||"rightHandSide".equals(node.getLocalName())
 166  
                                                                         ||"joinCriteria".equals(node.getLocalName())){
 167  2
                                                                 Object childBean = pc.getDelegate().parsePropertySubElement((Element)node, pc.getContainingBeanDefinition());
 168  2
                                                                 builder.addPropertyValue(node.getLocalName(), childBean);
 169  2
                                                         }else{
 170  56
                                                                 builder.addPropertyValue(node.getLocalName(), node.getTextContent());
 171  
                                                         }
 172  
                                                 }
 173  
                                         }
 174  
                     }
 175  
                         }
 176  
                 }
 177  44
         }
 178  
 
 179  
         private boolean isUnwrappedList(String localName) {
 180  74
                 return localName.equals("subSearchParamMappings")||
 181  
                localName.equals("comparison")||
 182  
                localName.equals("subSearch")||
 183  
                localName.equals("joinResultMapping");
 184  
         }
 185  
         
 186  
     //This is called to resolve tag names to field names based on the element and parent element local names
 187  
         private String resolveFieldName(String parentName, String nodeName) {
 188  38
                 if("comparison".equals(nodeName)){
 189  0
                         return "comparisons";
 190  
                 }
 191  38
                 if("subSearch".equals(nodeName)){
 192  2
                         return "subSearches";
 193  
                 }
 194  36
                 if("joinResultMapping".equals(nodeName)){
 195  2
                         return "joinResultMappings";
 196  
                 }
 197  34
                 if("joinCriteria".equals(parentName)&&"type".equals(nodeName)){
 198  2
                         return "joinType";
 199  
                 }
 200  
 
 201  32
                 return nodeName;
 202  
         }
 203  
         
 204  
     //This builds up a list of the child nodes so that the spring parseListElement can be used
 205  
     //it also translates <fooRef> elements into straight spring <ref> elements
 206  
     private Element getChildList(Element element, String localName) {
 207  
             try{
 208  
                     //Create a new document to contain our list of elements
 209  4
                     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 210  4
                     DocumentBuilder builder = dbf.newDocumentBuilder();
 211  4
                     Document doc = builder.newDocument();
 212  
         
 213  4
                     Element root = doc.createElement("listRoot");
 214  
                     
 215  96
                 for(int i = 0;i<element.getChildNodes().getLength();i++){
 216  92
                     Node node = element.getChildNodes().item(i);
 217  92
                     if(Node.ELEMENT_NODE == node.getNodeType() && localName.equals(node.getLocalName())){
 218  
                             
 219  
                             //Copy the node from the spring config to our list
 220  12
                             Node copied = doc.importNode(node, true);
 221  12
                             root.appendChild(copied);
 222  
                     }
 223  92
                     if(Node.ELEMENT_NODE == node.getNodeType() && (localName+"Ref").equals(node.getLocalName())){
 224  
                             
 225  
                             //Create a new spring ref element and copy the bean attribute
 226  0
                             Element ref = doc.createElement("ref");
 227  0
                             ref.setAttribute("bean", ((Element)node).getAttribute("bean"));
 228  0
                             root.appendChild(ref);
 229  
                     }
 230  
                 }
 231  
                 
 232  4
                     return root;
 233  0
             }catch(Exception e){
 234  0
                     logger.error("Exception occured: ", e);
 235  
             }
 236  0
             return null;
 237  
         }
 238  
     
 239  
         private Element getFirstChildElement(Node node) {
 240  140
                 for(int i = 0;i<node.getChildNodes().getLength();i++){
 241  82
                         Node childNode = node.getChildNodes().item(i);
 242  82
                         if(Node.ELEMENT_NODE == childNode.getNodeType()){
 243  12
                                 return (Element) childNode;
 244  
                         }
 245  
                 }
 246  
                 
 247  58
                 return null;
 248  
         }
 249  
 
 250  
         private boolean isWrappedList(String localName) {
 251  86
                 return localName.equals("queryParams")||
 252  
                            localName.equals("resultColumns");
 253  
         }
 254  
         
 255  
         @Override
 256  
         protected String getParentName(Element element) {
 257  44
                 if(element.hasAttribute("parent")){
 258  0
             return element.getAttribute("parent");
 259  
                 }
 260  44
                 return super.getParentName(element);
 261  
         }
 262  
         
 263  
         @Override
 264  
         protected boolean shouldGenerateIdAsFallback() {
 265  38
                 return true;
 266  
         }
 267  
 }