001/** 002 * Copyright 2005-2017 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.xml; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.Iterator; 023import java.util.List; 024 025import javax.sql.DataSource; 026import javax.xml.parsers.ParserConfigurationException; 027 028import org.apache.commons.lang.StringUtils; 029import org.jdom.Document; 030import org.jdom.Element; 031import org.jdom.JDOMException; 032import org.jdom.Namespace; 033import org.kuali.rice.core.api.config.ConfigurationException; 034import org.kuali.rice.core.api.util.xml.XmlException; 035import org.kuali.rice.core.api.util.xml.XmlHelper; 036import org.kuali.rice.kim.api.identity.CodedAttribute; 037import org.kuali.rice.kim.api.identity.email.EntityEmail; 038import org.kuali.rice.kim.impl.identity.email.EntityEmailBo; 039import org.kuali.rice.kim.impl.identity.employment.EntityEmploymentBo; 040import org.kuali.rice.kim.impl.identity.entity.EntityBo; 041import org.kuali.rice.kim.impl.identity.name.EntityNameBo; 042import org.kuali.rice.kim.impl.identity.principal.PrincipalBo; 043import org.kuali.rice.kim.impl.identity.type.EntityTypeContactInfoBo; 044import org.kuali.rice.kim.impl.services.KimImplServiceLocator; 045import org.kuali.rice.krad.data.KradDataServiceLocator; 046import org.kuali.rice.krad.data.platform.MaxValueIncrementerFactory; 047import org.xml.sax.SAXException; 048 049/** 050 * Parses users from XML. 051 * 052 * This is really meant for use only in the unit tests and was written to help ease 053 * transition over to KIM. There are numerous unit tests which took advantage of 054 * the ability to import "users" from XML in KEW. KIM does not provide XML 055 * import capabilities in the initial implementation so this class provides that. 056 * 057 * @author Kuali Rice Team (rice.collab@kuali.org) 058 * 059 */ 060public class UserXmlParser { 061 062 private static final Namespace NAMESPACE = Namespace.getNamespace("", "ns:workflow/User"); 063 064 private static final String USERS_ELEMENT = "users"; 065 private static final String USER_ELEMENT = "user"; 066 private static final String WORKFLOW_ID_ELEMENT = "workflowId"; 067 private static final String AUTHENTICATION_ID_ELEMENT = "authenticationId"; 068 private static final String PRINCIPAL_ID_ELEMENT = "principalId"; 069 private static final String PRINCIPAL_NAME_ELEMENT = "principalName"; 070 private static final String EMPL_ID_ELEMENT = "emplId"; 071 private static final String EMAIL_ELEMENT = "emailAddress"; 072 private static final String GIVEN_NAME_ELEMENT = "givenName"; 073 private static final String LAST_NAME_ELEMENT = "lastName"; 074 private static final String TYPE_ELEMENT = "type"; 075 076 private DataSource kimDataSource; 077 078 public void parseUsers(InputStream input) throws IOException, XmlException { 079 try { 080 Document doc = XmlHelper.trimSAXXml(input); 081 Element root = doc.getRootElement(); 082 parseUsers(root); 083 } catch (JDOMException e) { 084 throw new XmlException("Parse error.", e); 085 } catch (SAXException e){ 086 throw new XmlException("Parse error.",e); 087 } catch(ParserConfigurationException e){ 088 throw new XmlException("Parse error.",e); 089 } 090 } 091 092 public void parseUsers(Element root) throws XmlException { 093 for (Iterator usersElementIt = root.getChildren(USERS_ELEMENT, NAMESPACE).iterator(); usersElementIt.hasNext();) { 094 Element usersElement = (Element) usersElementIt.next(); 095 for (Iterator iterator = usersElement.getChildren(USER_ELEMENT, NAMESPACE).iterator(); iterator.hasNext();) { 096 Element userElement = (Element) iterator.next(); 097 EntityBo entity = constructEntity(userElement); 098 constructPrincipal(userElement, entity.getId()); 099 } 100 } 101 } 102 103 protected EntityBo constructEntity(Element userElement) { 104 String firstName = userElement.getChildTextTrim(GIVEN_NAME_ELEMENT, NAMESPACE); 105 String lastName = userElement.getChildTextTrim(LAST_NAME_ELEMENT, NAMESPACE); 106 String emplId = userElement.getChildTextTrim(EMPL_ID_ELEMENT, NAMESPACE); 107 String entityTypeCode = userElement.getChildTextTrim(TYPE_ELEMENT, NAMESPACE); 108 if (StringUtils.isBlank(entityTypeCode)) { 109 entityTypeCode = "PERSON"; 110 } 111 112 Long entityId = new Long(MaxValueIncrementerFactory.getIncrementer(getKimDataSource(), "KRIM_ENTITY_ID_S") 113 .nextLongValue()); 114 115 // if they define an empl id, let's set that up 116 EntityEmploymentBo emplInfo = null; 117 if (!StringUtils.isBlank(emplId)) { 118 emplInfo = new EntityEmploymentBo(); 119 emplInfo.setActive(true); 120 emplInfo.setEmployeeId(emplId); 121 emplInfo.setPrimary(true); 122 emplInfo.setEntityId("" + entityId); 123 emplInfo.setId(emplId); 124 emplInfo.setEntityAffiliationId(null); 125 } 126 127 128 EntityBo entity = new EntityBo(); 129 entity.setActive(true); 130 entity.setId("" + entityId); 131 List<EntityEmploymentBo> emplInfos = new ArrayList<EntityEmploymentBo>(); 132 if (emplInfo != null) { 133 emplInfos.add(emplInfo); 134 } 135 entity.setEmploymentInformation(emplInfos); 136 137 EntityTypeContactInfoBo entityType = new EntityTypeContactInfoBo(); 138 entityType.setEntityTypeCode(entityTypeCode); 139 entityType.setEntityId(entity.getId()); 140 entityType.setActive(true); 141 String emailAddress = userElement.getChildTextTrim(EMAIL_ELEMENT, NAMESPACE); 142 if (!StringUtils.isBlank(emailAddress)) { 143 Long emailId = new Long(MaxValueIncrementerFactory.getIncrementer(getKimDataSource(), 144 "KRIM_ENTITY_EMAIL_ID_S").nextLongValue()); 145 146 EntityEmail.Builder email = EntityEmail.Builder.create(); 147 email.setActive(true); 148 email.setId("" + emailId); 149 email.setEntityTypeCode(entityTypeCode); 150 // must be in krim_email_typ_t.email_typ_cd: 151 email.setEmailType(CodedAttribute.Builder.create("WRK")); 152 //email.setVersionNumber(new Long(1)); 153 email.setEmailAddress(emailAddress); 154 email.setDefaultValue(true); 155 email.setEntityId(entity.getId()); 156 List<EntityEmailBo> emailAddresses = new ArrayList<EntityEmailBo>(1); 157 emailAddresses.add(EntityEmailBo.from(email.build())); 158 entityType.setEmailAddresses(emailAddresses); 159 } 160 List<EntityTypeContactInfoBo> entityTypes = new ArrayList<EntityTypeContactInfoBo>(1); 161 entityTypes.add(entityType); 162 entity.setEntityTypeContactInfos(entityTypes); 163 164 if (!StringUtils.isBlank(firstName) || !StringUtils.isBlank(lastName)) { 165 Long entityNameId = MaxValueIncrementerFactory.getIncrementer(getKimDataSource(), "KRIM_ENTITY_NM_ID_S") 166 .nextLongValue(); 167 EntityNameBo name = new EntityNameBo(); 168 name.setActive(true); 169 name.setId("" + entityNameId); 170 name.setEntityId(entity.getId()); 171 // must be in krim_ent_nm_typ_t.ent_nm_typ_cd 172 name.setNameCode("PRFR"); 173 name.setFirstName(firstName); 174 name.setMiddleName(""); 175 name.setLastName(lastName); 176 name.setDefaultValue(true); 177 178 entity.setNames(Collections.singletonList(name)); 179 } 180 181 entity = KradDataServiceLocator.getDataObjectService().save(entity); 182 183 return entity; 184 } 185 186 protected PrincipalBo constructPrincipal(Element userElement, String entityId) { 187 String principalId = userElement.getChildTextTrim(WORKFLOW_ID_ELEMENT, NAMESPACE); 188 if (principalId == null) { 189 principalId = userElement.getChildTextTrim(PRINCIPAL_ID_ELEMENT, NAMESPACE); 190 } 191 String principalName = userElement.getChildTextTrim(AUTHENTICATION_ID_ELEMENT, NAMESPACE); 192 if (principalName == null) { 193 principalName = userElement.getChildTextTrim(PRINCIPAL_NAME_ELEMENT, NAMESPACE); 194 } 195 196 PrincipalBo principal = new PrincipalBo(); 197 principal.setActive(true); 198 principal.setPrincipalId(principalId); 199 principal.setPrincipalName(principalName); 200 principal.setEntityId(entityId); 201 principal = KradDataServiceLocator.getDataObjectService().save(principal); 202 203 return principal; 204 } 205 206 public DataSource getKimDataSource() { 207 if (kimDataSource == null) { 208 // TODO - nasty, nasty, nasty - in general the problem here is the fact that UserXmlParser is even using 209 // KIM sequences in the first place 210 kimDataSource = KimImplServiceLocator.getDataSource(); 211 if (kimDataSource == null) { 212 throw new ConfigurationException("Failed to locate 'kimDataSource'"); 213 } 214 } 215 return kimDataSource; 216 } 217 218 public void setKimDataSource(DataSource kimDataSource) { 219 this.kimDataSource = kimDataSource; 220 } 221}