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