View Javadoc
1   /**
2    * Copyright 2005-2015 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 java.io.IOException;
19  import java.io.InputStream;
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import javax.sql.DataSource;
26  import javax.xml.parsers.ParserConfigurationException;
27  
28  import org.apache.commons.lang.StringUtils;
29  import org.jdom.Document;
30  import org.jdom.Element;
31  import org.jdom.JDOMException;
32  import org.jdom.Namespace;
33  import org.kuali.rice.core.api.config.ConfigurationException;
34  import org.kuali.rice.core.api.util.xml.XmlException;
35  import org.kuali.rice.core.api.util.xml.XmlHelper;
36  import org.kuali.rice.kim.api.identity.CodedAttribute;
37  import org.kuali.rice.kim.api.identity.email.EntityEmail;
38  import org.kuali.rice.kim.impl.identity.email.EntityEmailBo;
39  import org.kuali.rice.kim.impl.identity.employment.EntityEmploymentBo;
40  import org.kuali.rice.kim.impl.identity.entity.EntityBo;
41  import org.kuali.rice.kim.impl.identity.name.EntityNameBo;
42  import org.kuali.rice.kim.impl.identity.principal.PrincipalBo;
43  import org.kuali.rice.kim.impl.identity.type.EntityTypeContactInfoBo;
44  import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
45  import org.kuali.rice.krad.data.KradDataServiceLocator;
46  import org.kuali.rice.krad.data.platform.MaxValueIncrementerFactory;
47  import org.xml.sax.SAXException;
48  
49  /**
50   * Parses users from XML.
51   *
52   * This is really meant for use only in the unit tests and was written to help ease
53   * transition over to KIM.  There are numerous unit tests which took advantage of
54   * the ability to import "users" from XML in KEW.  KIM does not provide XML
55   * import capabilities in the initial implementation so this class provides that.
56   *
57   * @author Kuali Rice Team (rice.collab@kuali.org)
58   *
59   */
60  public class UserXmlParser {
61  
62      private static final Namespace NAMESPACE = Namespace.getNamespace("", "ns:workflow/User");
63  
64      private static final String USERS_ELEMENT = "users";
65      private static final String USER_ELEMENT = "user";
66      private static final String WORKFLOW_ID_ELEMENT = "workflowId";
67      private static final String AUTHENTICATION_ID_ELEMENT = "authenticationId";
68      private static final String PRINCIPAL_ID_ELEMENT = "principalId";
69      private static final String PRINCIPAL_NAME_ELEMENT = "principalName";
70      private static final String EMPL_ID_ELEMENT = "emplId";
71      private static final String EMAIL_ELEMENT = "emailAddress";
72      private static final String GIVEN_NAME_ELEMENT = "givenName";
73      private static final String LAST_NAME_ELEMENT = "lastName";
74      private static final String TYPE_ELEMENT = "type";
75  
76      private DataSource kimDataSource;
77  
78      public void parseUsers(InputStream input) throws IOException, XmlException {
79          try {
80              Document doc = XmlHelper.trimSAXXml(input);
81              Element root = doc.getRootElement();
82              parseUsers(root);
83          } catch (JDOMException e) {
84              throw new XmlException("Parse error.", e);
85          } catch (SAXException e){
86              throw new XmlException("Parse error.",e);
87          } catch(ParserConfigurationException e){
88              throw new XmlException("Parse error.",e);
89          }
90      }
91  
92      public void parseUsers(Element root) throws XmlException {
93      	for (Iterator usersElementIt = root.getChildren(USERS_ELEMENT, NAMESPACE).iterator(); usersElementIt.hasNext();) {
94      		Element usersElement = (Element) usersElementIt.next();
95      		for (Iterator iterator = usersElement.getChildren(USER_ELEMENT, NAMESPACE).iterator(); iterator.hasNext();) {
96      			Element userElement = (Element) iterator.next();
97      			EntityBo entity = constructEntity(userElement);
98      			constructPrincipal(userElement, entity.getId());
99      		}
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 }