Coverage Report - org.kuali.rice.kew.xml.GroupXmlParser
 
Classes in this File Line Coverage Branch Coverage Complexity
GroupXmlParser
0%
0/168
0%
0/82
9.714
 
 1  
 /**
 2  
  * Copyright 2005-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kew.xml;
 17  
 
 18  
 import org.jdom.Document;
 19  
 import org.jdom.Element;
 20  
 import org.jdom.JDOMException;
 21  
 import org.kuali.rice.core.api.util.xml.XmlException;
 22  
 import org.kuali.rice.core.api.util.xml.XmlHelper;
 23  
 import org.kuali.rice.kew.api.KewApiConstants;
 24  
 import org.kuali.rice.kew.util.Utilities;
 25  
 import org.kuali.rice.kim.api.KimConstants;
 26  
 import org.kuali.rice.kim.api.group.Group;
 27  
 import org.kuali.rice.kim.api.group.GroupService;
 28  
 import org.kuali.rice.kim.api.identity.IdentityService;
 29  
 import org.kuali.rice.kim.api.identity.principal.Principal;
 30  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 31  
 import org.kuali.rice.kim.api.type.KimType;
 32  
 import org.kuali.rice.kim.api.type.KimTypeAttribute;
 33  
 import org.xml.sax.SAXException;
 34  
 
 35  
 import javax.xml.parsers.ParserConfigurationException;
 36  
 import java.io.IOException;
 37  
 import java.io.InputStream;
 38  
 import java.util.ArrayList;
 39  
 import java.util.HashMap;
 40  
 import java.util.List;
 41  
 import java.util.Map;
 42  
 
 43  
 import static org.kuali.rice.core.api.impex.xml.XmlConstants.*;
 44  
 
 45  
 
 46  
 /**
 47  
  * Parses groups from XML.
 48  
  *
 49  
  * @see Group
 50  
  *
 51  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 52  
  *
 53  
  */
 54  0
 public class GroupXmlParser {
 55  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GroupXmlParser.class);
 56  
     private static final boolean DEFAULT_ACTIVE_VALUE = true;
 57  
     private static final String DEFAULT_GROUP_DESCRIPTION = "";
 58  0
     private HashMap<String, List<String>> memberGroupIds = new HashMap<String, List<String>>();
 59  0
     private HashMap<String, List<String>> memberGroupNames = new HashMap<String, List<String>>();
 60  0
     private HashMap<String, List<String>> memberPrincipalIds = new HashMap<String, List<String>>();
 61  0
     private Map<String, String> groupAttributes = new HashMap<String, String>();
 62  
 
 63  
     public List<Group> parseGroups(InputStream input) throws IOException, XmlException {
 64  
         try {
 65  0
             Document doc = XmlHelper.trimSAXXml(input);
 66  0
             Element root = doc.getRootElement();
 67  0
             return parseGroups(root);
 68  0
         } catch (JDOMException e) {
 69  0
             throw new XmlException("Parse error.", e);
 70  0
         } catch (SAXException e){
 71  0
             throw new XmlException("Parse error.",e);
 72  0
         } catch(ParserConfigurationException e){
 73  0
             throw new XmlException("Parse error.",e);
 74  
         }
 75  
     }
 76  
 
 77  
 
 78  
     /**
 79  
      * Parses and saves groups
 80  
      * @param element top-level 'data' element which should contain a <groups> child element
 81  
      * @return a list of parsed and saved, current, groups;
 82  
      * @throws XmlException
 83  
      */
 84  
     @SuppressWarnings("unchecked")
 85  
         public List<Group> parseGroups(Element element) throws XmlException {
 86  0
         List<Group> groups = new ArrayList<Group>();
 87  0
         for (Element groupsElement: (List<Element>) element.getChildren(GROUPS, GROUP_NAMESPACE)) {
 88  
 
 89  0
             for (Element groupElement: (List<Element>) groupsElement.getChildren(GROUP, GROUP_NAMESPACE)) {
 90  0
                 groups.add(parseGroup(groupElement));
 91  
             }
 92  
         }
 93  0
         for (Group group : groups) {
 94  0
             GroupService groupService = KimApiServiceLocator.getGroupService();
 95  
             // check if group already exists
 96  0
             Group foundGroup = groupService.getGroupByNameAndNamespaceCode(group.getNamespaceCode(), group.getName());
 97  
 
 98  0
             if (foundGroup == null) {
 99  0
                 if ( LOG.isInfoEnabled() ) {
 100  0
                         LOG.info("Group named '" + group.getName() + "' not found, creating new group named '" + group.getName() + "'");
 101  
                 }
 102  
                 try {
 103  0
                     Group newGroup =  groupService.createGroup(group);
 104  
 
 105  0
                     String key = newGroup.getNamespaceCode().trim() + KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + newGroup.getName().trim();
 106  0
                     addGroupMembers(newGroup, key);
 107  0
                 } catch (Exception e) {
 108  0
                     throw new RuntimeException("Error creating group with name '" + group.getName() + "'", e);
 109  0
                 }
 110  
             } else {
 111  0
                     if ( LOG.isInfoEnabled() ) {
 112  0
                             LOG.info("Group named '" + group.getName() + "' found, creating a new version");
 113  
                     }
 114  
                 try {
 115  0
                     Group.Builder builder = Group.Builder.create(foundGroup);
 116  0
                     builder.setActive(group.isActive());
 117  0
                     builder.setDescription(group.getDescription());
 118  0
                     builder.setKimTypeId(group.getKimTypeId());
 119  
 
 120  
                     //builder.setVersionNumber(foundGroup.getVersionNumber());
 121  0
                     group = builder.build();
 122  0
                     groupService.updateGroup(foundGroup.getId(), group);
 123  
 
 124  
                     //delete existing group members and replace with new
 125  0
                     groupService.removeAllMembers(foundGroup.getId());
 126  
 
 127  0
                     String key = group.getNamespaceCode().trim() + KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + group.getName().trim();
 128  0
                     addGroupMembers(group, key);
 129  
 
 130  0
                 } catch (Exception e) {
 131  0
                     throw new RuntimeException("Error updating group.", e);
 132  0
                 }
 133  
             }
 134  0
         }
 135  0
         return groups;
 136  
     }
 137  
 
 138  
     @SuppressWarnings("unchecked")
 139  
         private Group parseGroup(Element element) throws XmlException {
 140  
 
 141  
 
 142  
         // Type element and children (namespace and name)
 143  
 
 144  0
         String typeId = null;
 145  
         KimType kimTypeInfo;
 146  0
         List<KimTypeAttribute> kimTypeAttributes = new ArrayList<KimTypeAttribute>();
 147  0
         if (element.getChild(TYPE, GROUP_NAMESPACE) != null) {
 148  0
             Element typeElement = element.getChild(TYPE, GROUP_NAMESPACE);
 149  0
             String typeNamespace = typeElement.getChildText(NAMESPACE, GROUP_NAMESPACE);
 150  0
             String typeName = typeElement.getChildText(NAME, GROUP_NAMESPACE);
 151  0
             kimTypeInfo = KimApiServiceLocator.getKimTypeInfoService().findKimTypeByNameAndNamespace(typeNamespace, typeName);
 152  0
             if (kimTypeInfo != null) {
 153  0
                     typeId = kimTypeInfo.getId();
 154  0
                 kimTypeAttributes = kimTypeInfo.getAttributeDefinitions();
 155  
             } else  {
 156  0
                 throw new XmlException("Invalid type name and namespace specified.");
 157  
             }
 158  0
         } else { //set to default type
 159  0
             kimTypeInfo = KimApiServiceLocator.getKimTypeInfoService().findKimTypeByNameAndNamespace(KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, KimConstants.KIM_TYPE_DEFAULT_NAME);
 160  0
             if (kimTypeInfo != null) {
 161  0
                     typeId = kimTypeInfo.getId();
 162  0
                 kimTypeAttributes = kimTypeInfo.getAttributeDefinitions();
 163  
             } else {
 164  0
                     throw new RuntimeException("Failed to locate the 'Default' group type!  Please ensure that it's in your database.");
 165  
             }
 166  
         }
 167  
         //groupInfo.setKimTypeId(typeId);
 168  
 
 169  0
         String groupNamespace = element.getChildText(NAMESPACE, GROUP_NAMESPACE);
 170  0
         if (groupNamespace == null) {
 171  0
             throw new XmlException("Namespace must have a value.");
 172  
         }
 173  
 
 174  0
         String groupName = element.getChildText(NAME, GROUP_NAMESPACE);
 175  0
         if (groupName == null) {
 176  0
             throw new XmlException("Name must have a value.");
 177  
         }
 178  
 
 179  0
         Group.Builder groupInfo = Group.Builder.create(groupNamespace, groupName, typeId);
 180  0
         IdentityService identityService = KimApiServiceLocator.getIdentityService();
 181  
         //groupInfo.setGroupName(element.getChildText(NAME, GROUP_NAMESPACE));
 182  
 
 183  0
         String id = element.getChildText(ID, GROUP_NAMESPACE);
 184  0
         if (id != null) {
 185  0
             groupInfo.setId(id.trim());
 186  
         } else {
 187  
                 
 188  
         }
 189  
 
 190  0
         String description = element.getChildText(DESCRIPTION, GROUP_NAMESPACE);
 191  0
         if (description != null && !description.trim().equals("")) {
 192  0
             groupInfo.setDescription(description);
 193  
         }
 194  
 
 195  
         //Active Indicator
 196  0
         groupInfo.setActive(DEFAULT_ACTIVE_VALUE);
 197  0
         if (element.getChildText(ACTIVE, GROUP_NAMESPACE) != null) {
 198  0
             String active = element.getChildText(ACTIVE, GROUP_NAMESPACE).trim();
 199  0
             if (active.toUpperCase().equals("N") || active.toUpperCase().equals("FALSE")) {
 200  0
                 groupInfo.setActive(false);
 201  
             }
 202  
         }
 203  
 
 204  
         //Get list of attribute keys
 205  0
         List<String> validAttributeKeys = new ArrayList<String>();
 206  0
         for (KimTypeAttribute attribute : kimTypeAttributes) {
 207  0
             validAttributeKeys.add(attribute.getKimAttribute().getAttributeName());
 208  
         }
 209  
         //Group attributes
 210  0
         if (element.getChild(ATTRIBUTES, GROUP_NAMESPACE) != null) {
 211  0
             List<Element> attributes = element.getChild(ATTRIBUTES, GROUP_NAMESPACE).getChildren();
 212  
 
 213  0
             Map<String, String> attrMap = new HashMap<String, String>();
 214  0
             for (Element attr : attributes ) {
 215  0
                 attrMap.put(attr.getAttributeValue(KEY), attr.getAttributeValue(VALUE));
 216  0
                 if (!validAttributeKeys.contains(attr.getAttributeValue(KEY))) {
 217  0
                     throw new XmlException("Invalid attribute specified.");
 218  
                 }
 219  
             }
 220  0
             Map<String, String> groupAttributes = attrMap;
 221  0
             if (!groupAttributes.isEmpty()) {
 222  0
                 groupInfo.setAttributes(groupAttributes);
 223  
             }
 224  
         }
 225  
 
 226  
         //Group members
 227  
 
 228  0
         List<Element> members = null;
 229  0
         if(element.getChild(MEMBERS, GROUP_NAMESPACE) == null) {
 230  0
             members = new ArrayList<Element>();
 231  
         }
 232  
         else {
 233  0
             members = element.getChild(MEMBERS, GROUP_NAMESPACE).getChildren();
 234  
         }
 235  0
         for (Element member : members) {
 236  0
             String elementName = member.getName().trim();
 237  0
             if (elementName.equals(PRINCIPAL_NAME)) {
 238  0
                 String principalName = member.getText().trim();
 239  0
                 Principal principal = identityService.getPrincipalByPrincipalName(principalName);
 240  0
                 if (principal != null) {
 241  0
                     addPrincipalToGroup(groupInfo.getNamespaceCode(), groupInfo.getName(), principal.getPrincipalId());
 242  
                 } else {
 243  0
                     throw new XmlException("Principal Name "+principalName+" cannot be found.");
 244  
                 }
 245  0
             } else if (elementName.equals(PRINCIPAL_ID)) {
 246  0
                 String xmlPrincipalId = member.getText().trim();
 247  0
                 Principal principal = identityService.getPrincipal(xmlPrincipalId);
 248  0
                 if (principal != null) {
 249  0
                     addPrincipalToGroup(groupInfo.getNamespaceCode(), groupInfo.getName(), principal.getPrincipalId());
 250  
                 } else {
 251  0
                     throw new XmlException("Principal Id "+xmlPrincipalId+" cannot be found.");
 252  
                 }
 253  
             // Groups are handled differently since the member group may not be saved yet.  Therefore they need to be validated after the groups are saved.
 254  0
             } else if (elementName.equals(GROUP_ID)) {
 255  0
                 String xmlGroupId = member.getText().trim();
 256  0
                 addGroupToGroup(groupInfo.getNamespaceCode(), groupInfo.getName(), xmlGroupId);
 257  0
             } else if (elementName.equals(GROUP_NAME)) {
 258  0
                 String xmlGroupName = member.getChildText(NAME, GROUP_NAMESPACE).trim();
 259  0
                 String xmlGroupNamespace = member.getChildText(NAMESPACE, GROUP_NAMESPACE).trim();
 260  0
                 addGroupNameToGroup(groupInfo.getNamespaceCode(), groupInfo.getName(), xmlGroupNamespace, xmlGroupName);
 261  0
             } else {
 262  0
                 LOG.error("Unknown member element: " + elementName);
 263  
             }
 264  
 
 265  
 
 266  0
         }
 267  
 
 268  0
         return groupInfo.build();
 269  
 
 270  
     }
 271  
 
 272  
     private void addPrincipalToGroup(String groupNamespace, String groupName, String principalId) {
 273  0
         String key = groupNamespace.trim() + KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupName.trim();
 274  0
         List<String> principalIds = memberPrincipalIds.get(key);
 275  0
         if (principalIds == null) {
 276  0
             principalIds = new ArrayList<String>();
 277  
         }
 278  0
         principalIds.add(principalId);
 279  0
         memberPrincipalIds.put(key, principalIds);
 280  0
     }
 281  
 
 282  
     private void addGroupToGroup(String groupNamespace, String groupName, String groupId) {
 283  0
         String key = groupNamespace.trim() + KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupName.trim();
 284  0
         List<String> groupIds = memberGroupIds.get(key);
 285  0
         if (groupIds == null) {
 286  0
             groupIds = new ArrayList<String>();
 287  
         }
 288  0
         groupIds.add(groupId);
 289  0
         memberGroupIds.put(key, groupIds);
 290  0
     }
 291  
 
 292  
     private void addGroupNameToGroup(String groupNamespace, String groupName, String memberGroupNamespace, String memberGroupName) {
 293  0
         String key = groupNamespace.trim() + KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupName.trim();
 294  0
         List<String> groupNames = memberGroupNames.get(key);
 295  0
         if (groupNames == null) {
 296  0
             groupNames = new ArrayList<String>();
 297  
         }
 298  0
         groupNames.add(memberGroupNamespace.trim() + KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + memberGroupName.trim());
 299  0
         memberGroupNames.put(key, groupNames);
 300  0
     }
 301  
 
 302  
     private void addGroupMembers(Group groupInfo, String key) throws XmlException {
 303  0
         GroupService groupService = KimApiServiceLocator.getGroupService();
 304  0
         List<String> groupIds = memberGroupIds.get(key);
 305  0
         if (groupIds != null) {
 306  0
             for (String groupId : groupIds) {
 307  0
                 Group group = groupService.getGroup(groupId);
 308  0
                 if (group != null) {
 309  0
                     groupService.addGroupToGroup(group.getId(), groupInfo.getId());
 310  
                 } else {
 311  0
                     throw new XmlException("Group Id "+groupId+" cannot be found.");
 312  
                 }
 313  0
             }
 314  
         }
 315  0
         List<String> groupNames = memberGroupNames.get(key);
 316  0
         if (groupNames != null) {
 317  0
             for (String groupName : groupNames) {
 318  0
                 Group group = groupService.getGroupByNameAndNamespaceCode(Utilities.parseGroupNamespaceCode(groupName),
 319  
                         Utilities.parseGroupName(groupName));
 320  0
                 if (group != null) {
 321  0
                         groupService.addGroupToGroup(group.getId(), groupInfo.getId());
 322  
                 } else {
 323  0
                     throw new XmlException("Group "+groupName+" cannot be found.");
 324  
                 }
 325  0
             }
 326  
         }
 327  0
         List<String> principalIds = memberPrincipalIds.get(key);
 328  0
         if (principalIds != null) {
 329  0
             for (String principalId : principalIds) {
 330  0
                     groupService.addPrincipalToGroup(principalId, groupInfo.getId());
 331  
             }
 332  
         }
 333  
 
 334  0
     }
 335  
 }