0001: package org.tigris.scarab.util.xmlissues;
0002:
0003: /* ================================================================
0004: * Copyright (c) 2000-2002 CollabNet. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions are
0008: * met:
0009: *
0010: * 1. Redistributions of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * 2. Redistributions in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in the
0015: * documentation and/or other materials provided with the distribution.
0016: *
0017: * 3. The end-user documentation included with the redistribution, if
0018: * any, must include the following acknowlegement: "This product includes
0019: * software developed by Collab.Net <http://www.Collab.Net/>."
0020: * Alternately, this acknowlegement may appear in the software itself, if
0021: * and wherever such third-party acknowlegements normally appear.
0022: *
0023: * 4. The hosted project names must not be used to endorse or promote
0024: * products derived from this software without prior written
0025: * permission. For written permission, please contact info@collab.net.
0026: *
0027: * 5. Products derived from this software may not use the "Tigris" or
0028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
0029: * prior written permission of Collab.Net.
0030: *
0031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
0035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
0041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0042: *
0043: * ====================================================================
0044: *
0045: * This software consists of voluntary contributions made by many
0046: * individuals on behalf of Collab.Net.
0047: */
0048:
0049: import java.io.File;
0050: import java.io.FileNotFoundException;
0051: import java.io.IOException;
0052: import java.text.ParseException;
0053: import java.util.ArrayList;
0054: import java.util.Calendar;
0055: import java.util.HashMap;
0056: import java.util.HashSet;
0057: import java.util.Iterator;
0058: import java.util.List;
0059: import java.util.Locale;
0060: import java.util.Map;
0061: import java.util.Set;
0062:
0063: import org.apache.commons.collections.map.LinkedMap;
0064: import org.apache.commons.logging.Log;
0065: import org.apache.commons.logging.LogFactory;
0066: import org.apache.fulcrum.localization.Localization;
0067: import org.apache.fulcrum.security.util.TurbineSecurityException;
0068: import org.apache.torque.TorqueException;
0069: import org.apache.turbine.Turbine;
0070: import org.tigris.scarab.om.Activity;
0071: import org.tigris.scarab.om.ActivityManager;
0072: import org.tigris.scarab.om.ActivitySet;
0073: import org.tigris.scarab.om.ActivitySetManager;
0074: import org.tigris.scarab.om.ActivitySetType;
0075: import org.tigris.scarab.om.ActivitySetTypeManager;
0076: import org.tigris.scarab.om.ActivitySetTypePeer;
0077: import org.tigris.scarab.notification.ActivityType;
0078: import org.tigris.scarab.om.Attachment;
0079: import org.tigris.scarab.om.AttachmentManager;
0080: import org.tigris.scarab.om.AttachmentType;
0081: import org.tigris.scarab.om.Attribute;
0082: import org.tigris.scarab.om.AttributeOption;
0083: import org.tigris.scarab.om.AttributeOptionManager;
0084: import org.tigris.scarab.om.AttributeValue;
0085: import org.tigris.scarab.om.Depend;
0086: import org.tigris.scarab.om.DependManager;
0087: import org.tigris.scarab.om.Issue;
0088: import org.tigris.scarab.om.IssueManager;
0089: import org.tigris.scarab.om.IssueType;
0090: import org.tigris.scarab.om.Module;
0091: import org.tigris.scarab.om.ModuleManager;
0092: import org.tigris.scarab.om.RModuleOption;
0093: import org.tigris.scarab.om.RModuleOptionManager;
0094: import org.tigris.scarab.om.ScarabUser;
0095: import org.tigris.scarab.om.ScarabUserImpl;
0096: import org.tigris.scarab.om.ScarabUserManager;
0097: import org.tigris.scarab.tools.localization.L10NKey;
0098: import org.tigris.scarab.tools.localization.L10NKeySet;
0099: import org.tigris.scarab.util.AnonymousUserUtil;
0100: import org.tigris.scarab.util.ScarabConstants;
0101: import org.tigris.scarab.util.ScarabException;
0102:
0103: /**
0104: * <p>This class manages the validation and importing of issues.</p>
0105: *
0106: * <p>This classes has a format dictated by the <a
0107: * href="http://jakarta.apache.org/commons/betwixt/">Betwixt</a>
0108: * parser. As the parser extracts elements out of the XML file, it
0109: * looks for the public getters and setters in this class's signature
0110: * and thereby makes determinations on what JavaBean methods to call
0111: * in this class. Reading this source file in isolation: Doing so
0112: * would make it look like you could do things like remove the data
0113: * member 'issue' and its accessor methods because it looks as though
0114: * they are unused, whereas they are in fact signals to the Betwixt
0115: * parser: It reads them and interprets their presence and instruction
0116: * to create instances of issues from the XML being parsed.</p>
0117: *
0118: * <p>Also, of note, the design of this class is that, it has two
0119: * modes based off the setting of the inValidationMode class. When
0120: * parsing w/ the {@link #inValidationMode} flag set, the db is not
0121: * touched. The code just validates the XML's data content checking
0122: * the users exist in the db, that the attributes and modules
0123: * referenced already exit. A parse with the {@link
0124: * #inValidationMode} set to false will do actual insert of the XML
0125: * issues.</p>
0126: *
0127: * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
0128: * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
0129: * @version $Id: ScarabIssues.java 10162 2006-06-11 11:20:24Z hair $
0130: */
0131: public class ScarabIssues implements java.io.Serializable {
0132: private static final Log LOG = LogFactory
0133: .getLog(ScarabIssues.class);
0134:
0135: private XmlModule module = null;
0136:
0137: /**
0138: * Betwixt parser adds here instance of issues found in parsed xml.
0139: */
0140: private List issues = null;
0141:
0142: private String importType = null;
0143:
0144: private int importTypeCode = -1;
0145:
0146: private final List allDependencies = new ArrayList();
0147:
0148: /**
0149: * Maps issue IDs from the XML file to IDs assigned by the DB.
0150: */
0151: private final Map issueXMLMap = new HashMap();
0152:
0153: /**
0154: * Maps activity set IDs from the XML file to IDs assigned by the
0155: * DB.
0156: */
0157: private final Map activitySetIdMap = new HashMap();
0158:
0159: /**
0160: * Maps attachment IDs from the XML file to IDs assigned by the
0161: * DB.
0162: */
0163: private final Map attachmentIdMap = new HashMap();
0164:
0165: /**
0166: * Maps dependency IDs from the XML file to IDs assigned by the
0167: * DB.
0168: */
0169: private final List dependActivitySetId = new ArrayList();
0170:
0171: private static final int CREATE_SAME_DB = 1;
0172: private static final int CREATE_DIFFERENT_DB = 2;
0173: private static final int UPDATE_SAME_DB = 3;
0174:
0175: private static Attribute nullAttribute = null;
0176:
0177: /**
0178: * We default to be in validation mode. Insert only occurs
0179: * post-validation.
0180: */
0181: private boolean inValidationMode = true;
0182:
0183: /**
0184: * A record of any errors encountered during the import. Set by
0185: * ImportIssues after an instance is created during XML parsing.
0186: */
0187: ImportErrors importErrors;
0188:
0189: /**
0190: * The users referenced by the XML file.
0191: */
0192: private final Set importUsers = new HashSet();
0193:
0194: /** property for adding users during the import **/
0195: private final boolean addUsers;
0196:
0197: /**
0198: * The current file attachment handling code has a security bug
0199: * that can allow a user to see any file on the host that is
0200: * readable by scarab. It is not easy to exploit this hole, and
0201: * there are cases where we want to use the functionality and can
0202: * be sure the hole is not being exploited. So adding a flag to
0203: * disallow file attachments when importing through the UI.
0204: *
0205: * This flag is set by ImportIssues after our instance is created
0206: * during XML parsing.
0207: */
0208: private boolean allowFileAttachments = false;
0209:
0210: public ScarabIssues() {
0211: issues = new ArrayList();
0212: if (nullAttribute == null) {
0213: try {
0214: nullAttribute = Attribute.getInstance(0);
0215: } catch (Exception e) {
0216: LOG.warn("Could not assign nullAttribute", e);
0217: }
0218: }
0219: // fetch property here so it can be changed at runtime
0220: addUsers = Turbine.getConfiguration().getBoolean(
0221: ScarabConstants.IMPORT_ADD_USERS, false);
0222: }
0223:
0224: /**
0225: * Instances of this class will have their {@link
0226: * #allowFileAttachments} flag set to this value upon
0227: * instantiation. Current file attachment handling code has a
0228: * security bug that can allow a user to see any file on the host
0229: * that is readable by scarab. It is not easy to exploit this
0230: * hole, and there are cases where we want to use the
0231: * functionality and can be sure the hole is not being exploited.
0232: * So adding a flag to allow file attachments under certain
0233: * circumstances.
0234: */
0235: public void allowFileAttachments(final boolean flag) {
0236: this .allowFileAttachments = flag;
0237: }
0238:
0239: public void inValidationMode(final boolean flag) {
0240: inValidationMode = flag;
0241: }
0242:
0243: public void setImportType(final String value) {
0244: this .importType = value;
0245: if (importType.equals("create-same-db")) {
0246: importTypeCode = CREATE_SAME_DB;
0247: } else if (importType.equals("create-different-db")) {
0248: importTypeCode = CREATE_DIFFERENT_DB;
0249: } else if (importType.equals("update-same-db")) {
0250: importTypeCode = UPDATE_SAME_DB;
0251: }
0252: }
0253:
0254: public String getImportType() {
0255: return this .importType;
0256: }
0257:
0258: public int getImportTypeCode() {
0259: return importTypeCode;
0260: }
0261:
0262: /**
0263: * @return Map of original id -> new scarab id.
0264: */
0265: public Map getIDs() {
0266: return this .issueXMLMap;
0267: }
0268:
0269: public XmlModule getModule() {
0270: // it's ok to not define a module in the xml
0271: // just use the an empty module
0272: return (module != null) ? module : new XmlModule();
0273: }
0274:
0275: public void setModule(final XmlModule module) {
0276: LOG.debug("Module.setModule(): " + module.getName());
0277: this .module = module;
0278: }
0279:
0280: void doValidateUsers() {
0281: if (importUsers != null && !importUsers.isEmpty()) {
0282: for (Iterator itr = importUsers.iterator(); itr.hasNext();) {
0283: final String userStr = (String) itr.next();
0284: try {
0285: ScarabUser user = findUser(userStr);
0286: if (user == null && addUsers) {
0287: user = (ScarabUser) AnonymousUserUtil
0288: .getAnonymousUser();
0289: user.setUserName(userStr);
0290: user.setFirstName(userStr);
0291: user.setLastName(userStr);
0292: user
0293: .setEmail(userStr.indexOf('@') > 0 ? userStr
0294: : userStr + "@localhost");
0295: user.setPassword(userStr);
0296:
0297: user.createNewUser();
0298:
0299: // if we got here, then all must be good...
0300:
0301: ScarabUserImpl.confirmUser(userStr);
0302: // force the user to change their password the first time they login
0303: user.setPasswordExpire(Calendar.getInstance());
0304: }
0305: } catch (Exception e) {
0306: final String error = Localization.format(
0307: ScarabConstants.DEFAULT_BUNDLE_NAME,
0308: getLocale(), "CouldNotLocateUsername",
0309: userStr);
0310: importErrors.add(error);
0311: }
0312: }
0313: }
0314: }
0315:
0316: void doValidateDependencies() {
0317: if (allDependencies != null && !allDependencies.isEmpty()) {
0318: for (Iterator itr = allDependencies.iterator(); itr
0319: .hasNext();) {
0320: final XmlActivity activity = (XmlActivity) itr.next();
0321: final Dependency dependency = activity.getDependency();
0322: final String child = (String) issueXMLMap
0323: .get(dependency.getChild());
0324: final String parent = (String) issueXMLMap
0325: .get(dependency.getParent());
0326: if (parent == null || child == null) {
0327: LOG.debug("Could not find issues for parent '"
0328: + parent + "' and child '" + child + '\'');
0329: } else {
0330: try {
0331: final Issue parentIssueOM = IssueManager
0332: .getIssueById(parent);
0333: if (parentIssueOM == null) {
0334: throw new IllegalArgumentException(
0335: "Missing parent issue"); //EXCEPTION
0336: }
0337: } catch (Exception e) {
0338: final String error = Localization.format(
0339: ScarabConstants.DEFAULT_BUNDLE_NAME,
0340: getLocale(),
0341: "CouldNotLocateParentDepend", parent);
0342: importErrors.add(error);
0343: }
0344: try {
0345: final Issue childIssueOM = IssueManager
0346: .getIssueById(child);
0347: if (childIssueOM == null) {
0348: throw new IllegalArgumentException(
0349: "Missing child issue"); //EXCEPTION
0350: }
0351: } catch (Exception e) {
0352: final String error = Localization.format(
0353: ScarabConstants.DEFAULT_BUNDLE_NAME,
0354: getLocale(),
0355: "CouldNotLocateChildDepend", child);
0356: importErrors.add(error);
0357: }
0358: }
0359: }
0360: }
0361: allDependencies.clear();
0362: }
0363:
0364: void doHandleDependencies() throws ScarabException {
0365: LOG.debug("Number of dependencies found: "
0366: + allDependencies.size());
0367: for (Iterator itr = allDependencies.iterator(); itr.hasNext();) {
0368: final Object[] data = (Object[]) itr.next();
0369: final ActivitySet activitySetOM = (ActivitySet) data[0];
0370: final XmlActivity activity = (XmlActivity) data[1];
0371:
0372: final Dependency dependency = activity.getDependency();
0373: final String child = (String) issueXMLMap.get(dependency
0374: .getChild());
0375: final String parent = (String) issueXMLMap.get(dependency
0376: .getParent());
0377: if (parent == null || child == null) {
0378: LOG.debug("Could not find issues: parent: " + parent
0379: + " child: " + child);
0380: continue;
0381: }
0382:
0383: if (getImportTypeCode() == UPDATE_SAME_DB) {
0384: LOG
0385: .error("[TODO] update-same-db import type not yet implemented");
0386: // trick here is that dependencies don't have ids or unique keys to find the
0387: // correct existing instance against.
0388: } else {
0389: try {
0390: final String type = dependency.getType();
0391: final Depend newDependOM = DependManager
0392: .getInstance();
0393: final Issue parentIssueOM = IssueManager
0394: .getIssueById(parent);
0395: final Issue childIssueOM = IssueManager
0396: .getIssueById(child);
0397: newDependOM.setDefaultModule(parentIssueOM
0398: .getModule());
0399: newDependOM.setObservedId(parentIssueOM
0400: .getIssueId());
0401: newDependOM
0402: .setObserverId(childIssueOM.getIssueId());
0403: newDependOM.setDependType(type);
0404: LOG.debug("Dep: " + dependency.getId() + " Type: "
0405: + type + " Parent: " + parent + " Child: "
0406: + child);
0407: LOG.debug("XML Activity id: " + activity.getId());
0408: if (activity.isAddDependency()) {
0409: parentIssueOM.doAddDependency(activitySetOM,
0410: newDependOM, childIssueOM, null);
0411: LOG.debug("Added Dep Type: " + type
0412: + " Parent: " + parent + " Child: "
0413: + child);
0414: LOG
0415: .debug("----------------------------------------------------");
0416: } else if (activity.isDeleteDependency()) {
0417: parentIssueOM.doDeleteDependency(activitySetOM,
0418: newDependOM, null);
0419: LOG.debug("Deleted Dep Type: " + type
0420: + " Parent: " + parent + " Child: "
0421: + child);
0422: LOG
0423: .debug("----------------------------------------------------");
0424: } else if (activity.isUpdateDependency()) {
0425: final Depend oldDependOM = parentIssueOM
0426: .getDependency(childIssueOM);
0427: if (oldDependOM == null) {
0428: throw new IllegalArgumentException(
0429: "Whoops! Could not find the original dependency!"); //EXCEPTION
0430: }
0431: // we definitely know we are doing an update here.
0432: newDependOM.setDeleted(false);
0433: parentIssueOM.doChangeDependencyType(
0434: activitySetOM, oldDependOM,
0435: newDependOM, null);
0436: LOG.debug("Updated Dep Type: " + type
0437: + " Parent: " + parent + " Child: "
0438: + child);
0439: LOG
0440: .debug("Old Type: "
0441: + oldDependOM.getDependType()
0442: .getName()
0443: + " New type: "
0444: + newDependOM.getDependType()
0445: .getName());
0446: LOG
0447: .debug("----------------------------------------------------");
0448: }
0449: } catch (Exception e) {
0450: e.printStackTrace();
0451: throw new ScarabException(
0452: new L10NKey(
0453: "Failed to handle dependencies <localize me>"),
0454: e); //EXCEPTION
0455: }
0456: }
0457: }
0458: }
0459:
0460: public List getIssues() {
0461: return issues;
0462: }
0463:
0464: public void addIssue(final XmlIssue issue) throws ScarabException {
0465: LOG.debug("Module.addIssue(): " + issue.getId());
0466: try {
0467: if (inValidationMode) {
0468: importErrors
0469: .setParseContext((issue.hasModuleCode() ? ""
0470: : module.getCode())
0471: + issue.getId());
0472: doIssueValidateEvent(getModule(), issue);
0473: } else {
0474: doIssueEvent(getModule(), issue);
0475: }
0476: } catch (TorqueException e) {
0477: e.printStackTrace();
0478: throw new ScarabException(new L10NKey(
0479: "Exception adding issue" + issue.getId()), e); // FIXME localise
0480: } catch (ParseException e) {
0481: e.printStackTrace();
0482: throw new ScarabException(new L10NKey(
0483: "Exception adding issue" + issue.getId()), e); // FIXME localise
0484: } finally {
0485: importErrors.setParseContext(null);
0486: }
0487: }
0488:
0489: /**
0490: * Validates the data from a XML representation of an issue.
0491: * Examines as much of the data as possible, even if errors are
0492: * encountered in parent data.
0493: *
0494: * @param module The module containing <code>issue</code>.
0495: * @param issue The issue to validate.
0496: */
0497: private void doIssueValidateEvent(final XmlModule module,
0498: final XmlIssue issue) throws TorqueException {
0499: // Check for the existance of the module.
0500: Module moduleOM = null;
0501: try {
0502: moduleOM = getModuleForIssue(module, issue);
0503: if (moduleOM == null) {
0504: throw new IllegalArgumentException(); //EXCEPTION
0505: }
0506:
0507: // TODO: Handle user import. Until then, ignore the
0508: // module's owner.
0509: //importUsers.add(module.getOwner());
0510: } catch (Exception e) {
0511: final Object[] args = (issue.hasModuleCode() ? new Object[] {
0512: null, issue.getModuleCode(), module.getDomain() }
0513: : new Object[] { module.getName(),
0514: module.getCode(), module.getDomain() });
0515: final String error = Localization.format(
0516: ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(),
0517: "CouldNotFindModule", args);
0518: importErrors.add(error);
0519: }
0520:
0521: // Check for the existance of the issue type.
0522: IssueType issueTypeOM = null;
0523: try {
0524: issueTypeOM = IssueType
0525: .getInstance(issue.getArtifactType());
0526: if (issueTypeOM == null) {
0527: throw new IllegalArgumentException(); //EXCEPTION
0528: }
0529: } catch (Exception e) {
0530: final String error = Localization.format(
0531: ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(),
0532: "CouldNotFindIssueType", issue.getArtifactType());
0533: importErrors.add(error);
0534: }
0535: if (!moduleOM.getRModuleIssueType(issueTypeOM).getActive()) {
0536: final String error = Localization.format(
0537: ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(),
0538: "IssueTypeInactive", issue.getArtifactType());
0539: importErrors.add(error);
0540: }
0541: List moduleAttributeList = null;
0542: if (moduleOM != null) {
0543: moduleAttributeList = moduleOM.getAttributes(issueTypeOM);
0544: }
0545:
0546: final List activitySets = issue.getActivitySets();
0547: for (Iterator itr = activitySets.iterator(); itr.hasNext();) {
0548: final XmlActivitySet activitySet = (XmlActivitySet) itr
0549: .next();
0550: if (activitySet.getCreatedBy() != null) {
0551: importUsers.add(activitySet.getCreatedBy());
0552: }
0553: if (activitySet.getAttachment() != null) {
0554: final String attachCreatedBy = activitySet
0555: .getAttachment().getCreatedBy();
0556: if (attachCreatedBy != null) {
0557: importUsers.add(attachCreatedBy);
0558: }
0559: }
0560:
0561: // Validate the activity set's type.
0562: try {
0563: final ActivitySetType ttOM = ActivitySetTypeManager
0564: .getInstance(activitySet.getType());
0565: if (ttOM == null) {
0566: throw new IllegalArgumentException(); //EXCEPTION
0567: }
0568: } catch (Exception e) {
0569: final String error = Localization.format(
0570: ScarabConstants.DEFAULT_BUNDLE_NAME,
0571: getLocale(), "CouldNotFindActivitySetType",
0572: activitySet.getType());
0573: importErrors.add(error);
0574: }
0575:
0576: // Validate the activity set's date.
0577: validateDate(activitySet.getCreatedDate(), true);
0578:
0579: final List activities = activitySet.getActivities();
0580: for (Iterator itrb = activities.iterator(); itrb.hasNext();) {
0581: validateActivity(moduleOM, issueTypeOM,
0582: moduleAttributeList, activitySet,
0583: (XmlActivity) itrb.next());
0584: }
0585: }
0586: }
0587:
0588: /**
0589: * Validates an individual activity. A helper method for {@link
0590: * #doIssueValidateEvent(XmlModule, XmlIssue)}.
0591: *
0592: * @param moduleOM
0593: * @param issueTypeOM
0594: * @param moduleAttributeList The attributes for
0595: * <code>moduleOM</code> and <code>issueTypeOM</code>.
0596: * @param activitySet The transaction which <code>activity</code>
0597: * was a part of.
0598: * @param activity The activity to validate.
0599: * @see #doIssueValidateEvent(XmlModule, XmlIssue)
0600: */
0601: private void validateActivity(final Module moduleOM,
0602: final IssueType issueTypeOM,
0603: final List moduleAttributeList,
0604: final XmlActivitySet activitySet, final XmlActivity activity) {
0605: validateDate(activity.getEndDate(), false);
0606: if (activity.getOldUser() != null) {
0607: importUsers.add(activity.getOldUser());
0608: }
0609: if (activity.getNewUser() != null) {
0610: importUsers.add(activity.getNewUser());
0611: }
0612: final XmlAttachment activityAttachment = activity
0613: .getAttachment();
0614: if (activityAttachment != null) {
0615: if (allowFileAttachments
0616: && activityAttachment.getReconcilePath()
0617: && !new File(activityAttachment.getFilename())
0618: .exists()) {
0619: final String error = Localization.format(
0620: ScarabConstants.DEFAULT_BUNDLE_NAME,
0621: getLocale(), "CouldNotFindFileAttachment",
0622: activityAttachment.getFilename());
0623: importErrors.add(error);
0624: }
0625:
0626: validateDate(activityAttachment.getCreatedDate(), true);
0627: validateDate(activityAttachment.getModifiedDate(), false);
0628:
0629: final String attachCreatedBy = activityAttachment
0630: .getCreatedBy();
0631: if (attachCreatedBy != null) {
0632: importUsers.add(attachCreatedBy);
0633: }
0634: }
0635:
0636: // Get the Attribute associated with the Activity
0637: Attribute attributeOM = null;
0638: final String activityAttribute = activity.getAttribute();
0639: try {
0640: attributeOM = Attribute.getInstance(activityAttribute);
0641: if (attributeOM == null) {
0642: throw new Exception(); //EXCEPTION
0643: }
0644: } catch (Exception e) {
0645: final String error = Localization.format(
0646: ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(),
0647: "CouldNotFindGlobalAttribute", activityAttribute);
0648: importErrors.add(error);
0649: }
0650:
0651: if (attributeOM != null) {
0652: if (attributeOM.equals(nullAttribute)) {
0653: // Add any dependency activities to a list for later
0654: // processing.
0655: if (isDependencyActivity(activity)) {
0656: if (!isDuplicateDependency(activitySet)) {
0657: allDependencies.add(activity);
0658: LOG.debug("-------------Stored Dependency # "
0659: + allDependencies.size()
0660: + "-------------");
0661: }
0662:
0663: // Dependency activities don't require further
0664: // validation.
0665: return;
0666: }
0667: } else
0668: try {
0669: if (!attributeOM.isUserAttribute()) {
0670: // The null attribute will never be in this list.
0671: if (moduleAttributeList != null
0672: && moduleAttributeList
0673: .indexOf(attributeOM) < 0) {
0674: final String error = Localization
0675: .format(
0676: ScarabConstants.DEFAULT_BUNDLE_NAME,
0677: getLocale(),
0678: "CouldNotFindRModuleAttribute",
0679: activityAttribute);
0680: importErrors.add(error);
0681: } else if (activity.getNewOption() != null) {
0682: // check for global options
0683: AttributeOption attributeOptionOM = null;
0684: try {
0685: attributeOptionOM = AttributeOptionManager
0686: .getInstance(
0687: attributeOM,
0688: activity.getNewOption(),
0689: moduleOM, issueTypeOM);
0690: if (attributeOptionOM == null) {
0691: throw new Exception(); //EXCEPTION
0692: }
0693: } catch (Exception e) {
0694: final Object[] args = {
0695: activity.getNewOption(),
0696: attributeOM.getName(),
0697: issueTypeOM.getName() };
0698: final String error = Localization
0699: .format(
0700: ScarabConstants.DEFAULT_BUNDLE_NAME,
0701: getLocale(),
0702: "CouldNotFindAttributeOption",
0703: args);
0704: importErrors.add(error);
0705: }
0706: // check for module options
0707: try {
0708: final RModuleOption rmo = RModuleOptionManager
0709: .getInstance(moduleOM,
0710: issueTypeOM,
0711: attributeOptionOM);
0712: if (rmo == null) {
0713: throw new Exception(); //EXCEPTION
0714: }
0715: } catch (Exception e) {
0716: final Object[] args = {
0717: activity.getNewOption(),
0718: attributeOM.getName(),
0719: issueTypeOM.getName() };
0720: final String error = Localization
0721: .format(
0722: ScarabConstants.DEFAULT_BUNDLE_NAME,
0723: getLocale(),
0724: "CouldNotFindModuleAttributeOption",
0725: args);
0726: importErrors.add(error);
0727: }
0728: } else if (activity.getOldOption() != null) {
0729: AttributeOption attributeOptionOM = null;
0730: try {
0731: attributeOptionOM = AttributeOptionManager
0732: .getInstance(attributeOM,
0733: activity.getOldOption());
0734: if (attributeOptionOM == null) {
0735: throw new Exception(); //EXCEPTION
0736: }
0737: } catch (Exception e) {
0738: final String error = Localization
0739: .format(
0740: ScarabConstants.DEFAULT_BUNDLE_NAME,
0741: getLocale(),
0742: "CouldNotFindAttributeOption",
0743: activity.getOldOption());
0744: importErrors.add(error);
0745: }
0746: // check for module options
0747: try {
0748: final RModuleOption rmo = RModuleOptionManager
0749: .getInstance(moduleOM,
0750: issueTypeOM,
0751: attributeOptionOM);
0752: if (rmo == null) {
0753: throw new Exception(); //EXCEPTION
0754: }
0755: } catch (Exception e) {
0756: final Object[] args = {
0757: activity.getOldOption(),
0758: attributeOM.getName() };
0759: final String error = Localization
0760: .format(
0761: ScarabConstants.DEFAULT_BUNDLE_NAME,
0762: getLocale(),
0763: "CouldNotFindModuleAttributeOption",
0764: args);
0765: importErrors.add(error);
0766: }
0767: }
0768: }
0769: } catch (TorqueException ex) {
0770: ex.printStackTrace();
0771: importErrors.add(ex);
0772: }
0773: }
0774: }
0775:
0776: /**
0777: * Records any validation errors encountered.
0778: *
0779: * @param xmlDate The XML bean for the date.
0780: * @param required Whether a valid date is required (parse errors
0781: * are reported regardless of this setting).
0782: */
0783: private void validateDate(final BaseDate xmlDate,
0784: final boolean required) {
0785: try {
0786: // Report parse error failures even for optional dates.
0787: if ((xmlDate != null && xmlDate.getDate() == null)
0788: && required) {
0789: // Trigger error handling.
0790: throw new ParseException(null, -1); //EXCEPTION
0791: }
0792: } catch (ParseException e) {
0793: final String errorMsg = (e.getErrorOffset() != -1 ? ": "
0794: + e.getMessage() : "");
0795: final String[] args = { xmlDate.getTimestamp(),
0796: xmlDate.getFormat(), errorMsg };
0797: final String error = Localization.format(
0798: ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(),
0799: "InvalidDate", args);
0800: importErrors.add(error);
0801: }
0802: }
0803:
0804: private Issue createNewIssue(final XmlModule module,
0805: final XmlIssue issue, final String id)
0806: throws TorqueException, ScarabException {
0807: // get the instance of the module
0808: final Module moduleOM = getModuleForIssue(module, issue);
0809: // get the instance of the issue type
0810: final IssueType issueTypeOM = IssueType.getInstance(issue
0811: .getArtifactType());
0812: issueTypeOM.setName(issue.getArtifactType());
0813: // get me a new issue since we couldn't find one before
0814: final Issue issueOM = Issue.getNewInstance(moduleOM,
0815: issueTypeOM);
0816:
0817: // The import data may nominate its ID
0818: if (id != null) {
0819: // This will cause Issue.save() to use this ID
0820: issueOM.setIdCount(Integer.parseInt(id));
0821: }
0822:
0823: // create the issue in the database
0824: issueOM.save();
0825:
0826: // Add the mapping between the issue id and the id that was created.
0827: // This mapping is used dependency checking and printing out in
0828: // results list of original id and new id. The original issue id can be
0829: // null. In this case, have the original id show as 'null (index)'
0830: // where index is count into the issueXMLMap. We add the index to keep
0831: // the key unique. This substitute original id also shouldn't interfere
0832: // w/ issueXMLMap's use dependency checking.
0833: String issueID = "Null ("
0834: + Integer.toString(issueXMLMap.size()) + ")";
0835: if (issue.getId() != null) {
0836: issueID = (issue.hasModuleCode() ? "" : module.getCode())
0837: + issue.getId();
0838: }
0839: issueXMLMap.put(issueID, issueOM.getUniqueId());
0840:
0841: LOG.debug("Created new Issue: " + issueOM.getUniqueId());
0842: return issueOM;
0843: }
0844:
0845: private void doIssueEvent(final XmlModule module,
0846: final XmlIssue issue) throws TorqueException,
0847: ScarabException, ParseException {
0848: /////////////////////////////////////////////////////////////////////////////////
0849: // Get me an issue
0850: Issue issueOM = null;
0851: final String issueID = issue.hasModuleCode() ? "" : module
0852: .getCode()
0853: + issue.getId();
0854: if (getImportTypeCode() == CREATE_SAME_DB
0855: || getImportTypeCode() == CREATE_DIFFERENT_DB) {
0856: // Check if the new issue nominates an ID and if the database does
0857: // not already contain an issue with that ID
0858: if (issue.getId() != null
0859: && IssueManager.getIssueById(issueID) == null) {
0860: // Create the new issue with the nominated ID
0861: issueOM = createNewIssue(module, issue, issue.getId());
0862: } else {
0863: // Crate the new issue with an automatically allocated ID
0864: issueOM = createNewIssue(module, issue, null);
0865: }
0866: } else if (getImportTypeCode() == UPDATE_SAME_DB) // nice to specify just for searching/refactoring
0867: {
0868: issueOM = IssueManager.getIssueById(issueID);
0869:
0870: if (issueOM == null) {
0871: issueOM = createNewIssue(module, issue, null);
0872: } else {
0873: LOG
0874: .debug("Found Issue in db: "
0875: + issueOM.getUniqueId());
0876: }
0877: }
0878:
0879: /////////////////////////////////////////////////////////////////////////////////
0880:
0881: // Loop over the XML activitySets
0882: final List activitySets = issue.getActivitySets();
0883: LOG.debug("-----------------------------------");
0884: LOG.debug("Number of ActivitySets in Issue: "
0885: + activitySets.size());
0886: for (Iterator itr = activitySets.iterator(); itr.hasNext();) {
0887: final XmlActivitySet activitySet = (XmlActivitySet) itr
0888: .next();
0889: LOG.debug("Processing ActivitySet: " + activitySet.getId());
0890:
0891: /////////////////////////////////////////////////////////////////////////////////
0892: // Deal with the attachment for the activitySet
0893: final XmlAttachment activitySetAttachment = activitySet
0894: .getAttachment();
0895: Attachment activitySetAttachmentOM = null;
0896: if (activitySetAttachment != null) {
0897: if (getImportTypeCode() == UPDATE_SAME_DB) {
0898: try {
0899: activitySetAttachmentOM = AttachmentManager
0900: .getInstance(activitySetAttachment
0901: .getId());
0902: LOG
0903: .debug("Found existing ActivitySet Attachment");
0904: } catch (TorqueException e) {
0905: activitySetAttachmentOM = createAttachment(
0906: issueOM, activitySetAttachment);
0907: }
0908: } else {
0909: activitySetAttachmentOM = createAttachment(issueOM,
0910: activitySetAttachment);
0911: LOG.debug("Created ActivitySet Attachment object");
0912: }
0913: } else {
0914: LOG.debug("OK- No Attachment in this ActivitySet");
0915: }
0916:
0917: /////////////////////////////////////////////////////////////////////////////////
0918: // Attempt to get the activitySet OM
0919: boolean alreadyCreated = false;
0920: ActivitySet activitySetOM = null;
0921: if (getImportTypeCode() == UPDATE_SAME_DB) {
0922: try {
0923: activitySetOM = ActivitySetManager
0924: .getInstance(activitySet.getId());
0925: LOG.debug("Found ActivitySet: "
0926: + activitySet.getId() + " in db: "
0927: + activitySetOM.getActivitySetId());
0928: } catch (Exception e) {
0929: activitySetOM = ActivitySetManager.getInstance();
0930: }
0931: } else {
0932: // first try to get the ActivitySet from the internal map
0933: if (activitySetIdMap.containsKey(activitySet.getId())) {
0934: activitySetOM = ActivitySetManager
0935: .getInstance((String) activitySetIdMap
0936: .get(activitySet.getId()));
0937: alreadyCreated = true;
0938: LOG.debug("Found ActivitySet: "
0939: + activitySet.getId() + " in map: "
0940: + activitySetOM.getActivitySetId());
0941: } else // it hasn't been encountered previously
0942: {
0943: activitySetOM = ActivitySetManager.getInstance();
0944: LOG.debug("Created new ActivitySet");
0945: }
0946: }
0947:
0948: final ScarabUser activitySetCreatedByOM = findUser(activitySet
0949: .getCreatedBy());
0950:
0951: if (LOG.isDebugEnabled()) {
0952: LOG.debug("ActivitySet: " + activitySet.getId()
0953: + "; of type: " + activitySet.getType()
0954: + "; by: " + activitySet.getCreatedBy());
0955: LOG.debug(" alreadyCreated: " + alreadyCreated);
0956: }
0957:
0958: if (!alreadyCreated) {
0959: // Populate the ActivitySet
0960: // Get the ActivitySet type/createdby values (we know these are valid)
0961: final ActivitySetType ttOM = ActivitySetTypeManager
0962: .getInstance(activitySet.getType());
0963: activitySetOM.setActivitySetType(ttOM);
0964: if (activitySetCreatedByOM != null) {
0965: activitySetOM.setCreatedBy(activitySetCreatedByOM
0966: .getUserId());
0967: } else {
0968: // Anonymous user. better than nothing.
0969: try {
0970: activitySetOM
0971: .setCreatedBy(((ScarabUser) AnonymousUserUtil
0972: .getAnonymousUser())
0973: .getUserId());
0974: } catch (TurbineSecurityException e) {
0975: LOG
0976: .error("doIssueEvent: Cannot get Anonymous user: e");
0977: }
0978: }
0979: activitySetOM.setCreatedDate(activitySet
0980: .getCreatedDate().getDate());
0981: if (activitySetAttachmentOM != null) {
0982: activitySetAttachmentOM.save();
0983: activitySetOM
0984: .setAttachment(activitySetAttachmentOM);
0985: }
0986: activitySetOM.save();
0987: if (activitySet.getId() != null) {
0988: // if id is valid, save for later re-use.
0989: activitySetIdMap.put(activitySet.getId(),
0990: activitySetOM.getPrimaryKey().toString());
0991: }
0992: }
0993:
0994: // Determine if this ActivitySet should be marked as the
0995: // creation event
0996: final ActivitySet creationSet = issueOM
0997: .getActivitySetRelatedByCreatedTransId();
0998: if (ActivitySetTypePeer.CREATE_ISSUE__PK
0999: .equals(activitySetOM.getTypeId())
1000: || (ActivitySetTypePeer.MOVE_ISSUE__PK
1001: .equals(activitySetOM.getTypeId()) && (creationSet == null || activitySetOM
1002: .getCreatedDate().before(
1003: creationSet.getCreatedDate())))) {
1004: issueOM
1005: .setActivitySetRelatedByCreatedTransId(activitySetOM);
1006: }
1007:
1008: /////////////////////////////////////////////////////////////////////////////////
1009: // Deal with changing user attributes. this code needs to be in this *strange*
1010: // location because we look at the entire activityset in order to determine
1011: // that this is a change user activity set. of course in the future, it would
1012: // be really nice to create an activityset/activiy type that more accurately
1013: // reflects what type of change this is. so that it is easier to case for. for
1014: // now, we just look at some fingerprints to determine this information. -JSS
1015:
1016: if (activitySet.isChangeUserAttribute()) {
1017: final List activities = activitySet.getActivities();
1018: final XmlActivity activityA = (XmlActivity) activities
1019: .get(0);
1020: final XmlActivity activityB = (XmlActivity) activities
1021: .get(1);
1022:
1023: final ScarabUser assigneeOM = findUser(activityA
1024: .getOldUser());
1025: final ScarabUser assignerOM = findUser(activityB
1026: .getNewUser());
1027:
1028: final Attribute oldAttributeOM = Attribute
1029: .getInstance(activityA.getAttribute());
1030:
1031: final AttributeValue oldAttValOM = issueOM
1032: .getUserAttributeValue(assigneeOM,
1033: oldAttributeOM);
1034: if (oldAttValOM == null) {
1035: LOG.error("User '" + assigneeOM.getName()
1036: + "' was not previously '"
1037: + oldAttributeOM.getName()
1038: + "' to the issue!");
1039: }
1040:
1041: // Get the Attribute associated with the new Activity
1042: final Attribute newAttributeOM = Attribute
1043: .getInstance(activityB.getAttribute());
1044:
1045: issueOM.changeUserAttributeValue(activitySetOM,
1046: assigneeOM, assignerOM, oldAttValOM,
1047: newAttributeOM, null);
1048: LOG
1049: .debug("-------------Updated User AttributeValue------------");
1050: continue;
1051: }
1052:
1053: /////////////////////////////////////////////////////////////////////////////////
1054:
1055: // Deal with the activities in the activitySet
1056: final List activities = activitySet.getActivities();
1057: LOG.debug("Number of Activities in ActivitySet: "
1058: + activities.size());
1059:
1060: final LinkedMap avMap = issueOM
1061: .getModuleAttributeValuesMap();
1062: LOG.debug("Total Module Attribute Values: " + avMap.size());
1063: for (Iterator itrb = activities.iterator(); itrb.hasNext();) {
1064: final XmlActivity activity = (XmlActivity) itrb.next();
1065: LOG
1066: .debug("Looking at activity id: "
1067: + activity.getId());
1068:
1069: // Get the Attribute associated with the Activity
1070: final Attribute attributeOM = Attribute
1071: .getInstance(activity.getAttribute());
1072:
1073: // deal with the activity attachment (if there is one)
1074: final XmlAttachment activityAttachment = activity
1075: .getAttachment();
1076: Attachment activityAttachmentOM = null;
1077: if (activityAttachment != null) {
1078: // look for an existing attachment in the activity
1079: // the case is when we have a URL and we create it
1080: // and then delete it, the attachment id is still the
1081: // same so there is no reason to re-create the attachment
1082: // again.
1083: final String previousXmlId = activityAttachment
1084: .getId();
1085: final String previousId = (String) attachmentIdMap
1086: .get(previousXmlId);
1087: if (previousId == null) {
1088: activityAttachmentOM = createAttachment(
1089: issueOM, activityAttachment);
1090: activityAttachmentOM.save();
1091: attachmentIdMap.put(previousXmlId,
1092: activityAttachmentOM.getPrimaryKey()
1093: .toString());
1094:
1095: // Special case. After the Attachment object has been
1096: // saved, if the ReconcilePath == true, then assume
1097: // that the fileName is an absolute path to a file and
1098: // copy it to the right directory
1099: // structure under Scarab's path.
1100: if (allowFileAttachments
1101: && activityAttachment
1102: .getReconcilePath()) {
1103: try {
1104: activityAttachmentOM.copyFileFromTo(
1105: activityAttachment
1106: .getFilename(),
1107: activityAttachmentOM
1108: .getFullPath());
1109: } catch (FileNotFoundException ex) {
1110: // FIXME correct error message "ExceptionCouldNotFindFile"
1111: throw new ScarabException(
1112: L10NKeySet.ExceptionGeneral, ex);
1113: } catch (IOException ex) {
1114: // FIXME correct error message "ExceptionCouldNotReadFile"
1115: throw new ScarabException(
1116: L10NKeySet.ExceptionGeneral, ex);
1117: }
1118: }
1119: LOG.debug("Created Activity Attachment object");
1120: } else {
1121: activityAttachmentOM = AttachmentManager
1122: .getInstance(previousId);
1123: LOG.debug("Found existing Activity Attachment");
1124: }
1125: } else {
1126: LOG.debug("OK- No Attachment in this Activity");
1127: }
1128:
1129: // deal with null attributes (need to do this before we create the
1130: // activity right below because this will create its own activity).
1131: if (attributeOM.equals(nullAttribute)) {
1132: // add any dependency activities to a list for later processing
1133: if (isDependencyActivity(activity)) {
1134: if (!isDuplicateDependency(activitySet)) {
1135: final Object[] obj = { activitySetOM,
1136: activity, activityAttachmentOM };
1137: allDependencies.add(obj);
1138: dependActivitySetId
1139: .add(activitySet.getId());
1140: LOG
1141: .debug("-------------Stored Dependency # "
1142: + allDependencies.size()
1143: + "-------------");
1144: continue;
1145: }
1146: } else {
1147: // create the activity record.
1148: ActivityManager.createTextActivity(issueOM,
1149: nullAttribute, activitySetOM,
1150: ActivityType.getActivityType(activity
1151: .getActivityType()), activity
1152: .getDescription(),
1153: activityAttachmentOM, activity
1154: .getOldValue(), activity
1155: .getNewValue());
1156:
1157: LOG
1158: .debug("-------------Saved Null Attribute-------------");
1159: continue;
1160: }
1161: }
1162:
1163: // create the activityOM
1164: createActivity(activity, module, issueOM, attributeOM,
1165: activitySetOM);
1166:
1167: // check to see if this is a new activity or an update activity
1168: AttributeValue avalOM = null;
1169: for (Iterator moduleAttributeValueItr = avMap
1170: .mapIterator(); moduleAttributeValueItr
1171: .hasNext()
1172: && avalOM == null;) {
1173: final AttributeValue testAvalOM = (AttributeValue) avMap
1174: .get(moduleAttributeValueItr.next());
1175: final Attribute avalAttributeOM = testAvalOM
1176: .getAttribute();
1177:
1178: LOG.debug("Checking Attribute match: "
1179: + avalAttributeOM.getName() + " against: "
1180: + attributeOM.getName());
1181: if (avalAttributeOM.equals(attributeOM)) {
1182: avalOM = testAvalOM;
1183: }
1184: }
1185:
1186: if (avalOM != null) {
1187: final Attribute avalAttributeOM = avalOM
1188: .getAttribute();
1189: LOG.debug("Attributes match!");
1190: AttributeValue avalOM2 = null;
1191: if (!activity.isNewActivity()) {
1192: LOG.debug("Activity is not new.");
1193: avalOM2 = AttributeValue.getNewInstance(
1194: avalAttributeOM.getAttributeId(),
1195: avalOM.getIssue());
1196: avalOM2.setProperties(avalOM);
1197: }
1198:
1199: if (avalAttributeOM.isOptionAttribute()) {
1200: LOG.debug("We have an Option Attribute: "
1201: + avalAttributeOM.getName());
1202: final AttributeOption newAttributeOptionOM = AttributeOptionManager
1203: .getInstance(attributeOM, activity
1204: .getNewOption(), issueOM
1205: .getModule(), issueOM
1206: .getIssueType());
1207: if (activity.isNewActivity()) {
1208: if (newAttributeOptionOM != null) {
1209: avalOM.setOptionId(newAttributeOptionOM
1210: .getOptionId());
1211: avalOM.startActivitySet(activitySetOM);
1212: avalOM.setAttribute(attributeOM);
1213: avalOM.setActivityDescription(activity
1214: .getDescription());
1215: avalOM.save();
1216: LOG
1217: .debug("-------------Saved Attribute Value-------------");
1218: } else {
1219: LOG
1220: .warn("NewAttributeOptionOM is null for "
1221: + activity
1222: .getNewOption());
1223: }
1224: } else if (newAttributeOptionOM != null) {
1225: avalOM2.setOptionId(newAttributeOptionOM
1226: .getOptionId());
1227: final HashMap map = new HashMap();
1228: map.put(avalOM.getAttributeId(), avalOM2);
1229: issueOM.setAttributeValues(activitySetOM,
1230: map, null, activitySetCreatedByOM);
1231: LOG
1232: .debug("-------------Saved Option Attribute Change-------------");
1233: }
1234: } else if (avalAttributeOM.isUserAttribute()) {
1235: LOG.debug("We have a User Attribute: "
1236: + avalAttributeOM.getName());
1237: if (activity.isNewActivity()) {
1238: // Don't need to pass in the attachment because
1239: // it is already in the activitySetOM.
1240: // If we can't get an assignee new-user, then
1241: // use the activity set creator as assignee.
1242: ScarabUser assigneeOM = findUser(activity
1243: .getNewUser());
1244: assigneeOM = (assigneeOM != null) ? assigneeOM
1245: : activitySetCreatedByOM;
1246: if (assigneeOM != null) {
1247: issueOM.assignUser(activitySetOM,
1248: assigneeOM, null,
1249: avalAttributeOM, null);
1250: }
1251: LOG
1252: .debug("-------------Saved User Assign-------------");
1253: } else if (activity.isRemoveUserActivity()) {
1254: // remove a user activity
1255: final ScarabUser oldUserOM = findUser(activity
1256: .getOldUser());
1257: // need to reset the aval because the current one
1258: // is marked as new for some reason which causes an
1259: // insert and that isn't the right behavior here
1260: // (we want an update)
1261: avalOM = null;
1262: for (Iterator i = issueOM
1263: .getAttributeValues(avalAttributeOM)
1264: .iterator(); i.hasNext()
1265: && avalOM == null;) {
1266: final AttributeValue av = (AttributeValue) i
1267: .next();
1268: if (oldUserOM.getUserId().equals(
1269: av.getUserId())) {
1270: avalOM = av;
1271: }
1272: }
1273:
1274: if (avalOM == null) {
1275: if (LOG.isDebugEnabled()) {
1276: LOG
1277: .debug("Could not find previous AttributeValue assigning "
1278: + (oldUserOM == null ? "NULL"
1279: : oldUserOM
1280: .getUserName())
1281: + " to attribute "
1282: + avalAttributeOM
1283: .getName());
1284: }
1285: } else {
1286: // don't need to pass in the attachment because
1287: // it is already in the activitySetOM
1288: issueOM.deleteUser(activitySetOM,
1289: oldUserOM,
1290: activitySetCreatedByOM, avalOM,
1291: null);
1292: LOG
1293: .debug("-------------Saved User Remove-------------");
1294: }
1295: }
1296: } else if (avalAttributeOM.isTextAttribute()
1297: || avalAttributeOM.isIntegerAttribute()) {
1298: LOG.debug("We have a Text Attribute: "
1299: + avalAttributeOM.getName());
1300:
1301: avalOM.startActivitySet(activitySetOM);
1302: avalOM.setAttribute(attributeOM);
1303: avalOM.setActivityDescription(activity
1304: .getDescription());
1305:
1306: if (activity.isNewActivity()) {
1307: avalOM.setValue(activity.getNewValue());
1308: } else if (!activity.getNewValue().equals(
1309: avalOM.getValue())) {
1310: avalOM2.setValue(activity.getNewValue());
1311: avalOM.setProperties(avalOM2);
1312: }
1313:
1314: avalOM.save();
1315: LOG
1316: .debug("-------------Saved Attribute Value-------------");
1317: }
1318: }
1319: issueOM.save();
1320: LOG.debug("-------------Saved Issue-------------");
1321: }
1322: }
1323: }
1324:
1325: /**
1326: * Checks to see if there is a Dependency value for the Activity
1327: */
1328: private boolean isDependencyActivity(final XmlActivity activity) {
1329: return (activity.getDependency() != null);
1330: }
1331:
1332: private boolean isDuplicateDependency(
1333: final XmlActivitySet activitySet) {
1334: return (dependActivitySetId.indexOf(activitySet.getId()) > -1);
1335: }
1336:
1337: private Activity createActivity(final XmlActivity activity,
1338: final XmlModule module, final Issue issueOM,
1339: final Attribute attributeOM, final ActivitySet activitySetOM)
1340: throws TorqueException, ParseException, ScarabException {
1341: Activity activityOM = null;
1342: if (getImportTypeCode() == UPDATE_SAME_DB) {
1343: try {
1344: activityOM = ActivityManager.getInstance(activity
1345: .getId());
1346: } catch (Exception e) {
1347: activityOM = ActivityManager.getInstance();
1348: }
1349: } else {
1350: activityOM = ActivityManager.getInstance();
1351: }
1352:
1353: activityOM.setIssue(issueOM);
1354: activityOM.setAttribute(attributeOM);
1355: activityOM.setActivitySet(activitySetOM);
1356: if (activity.getEndDate() != null) {
1357: activityOM.setEndDate(activity.getEndDate().getDate());
1358: }
1359:
1360: // Set the attachment for the activity
1361: Attachment newAttachmentOM = null;
1362: if (activity.getAttachment() != null) {
1363: newAttachmentOM = createAttachment(issueOM, activity
1364: .getAttachment());
1365: newAttachmentOM.save();
1366: activityOM.setAttachment(newAttachmentOM);
1367: }
1368:
1369: LOG.debug("Created New Activity");
1370: return activityOM;
1371: }
1372:
1373: private Attachment createAttachment(final Issue issueOM,
1374: final XmlAttachment attachment) throws TorqueException,
1375: ScarabException, ParseException {
1376: final Attachment attachmentOM = AttachmentManager.getInstance();
1377: attachmentOM.setIssue(issueOM);
1378: final AttachmentType type = AttachmentType
1379: .getInstance(attachment.getType());
1380: if (allowFileAttachments
1381: || !Attachment.FILE__PK.equals(type
1382: .getAttachmentTypeId())) {
1383: attachmentOM.setName(attachment.getName());
1384: attachmentOM.setAttachmentType(type);
1385: attachmentOM.setMimeType(attachment.getMimetype());
1386: attachmentOM.setFileName(attachment.getFilename());
1387: attachmentOM.setData(attachment.getData());
1388: } else {
1389: // add a comment that the file will not be imported. An alternative would be
1390: // to skip the activity altogether, but we will then need to check that there
1391: // are other activities or we need to completely ignore the ActivitySet
1392: attachmentOM.setName("comment");
1393: attachmentOM.setTypeId(Attachment.COMMENT__PK);
1394: attachmentOM.setMimeType("text/plain");
1395: String text = "File, "
1396: + attachment.getFilename()
1397: + ", was not imported. The old description follows:\n\n"
1398: + attachment.getName();
1399: final String data = attachment.getData(); // this should be null, but just in case
1400: if (data != null) {
1401: text += "\n\n" + data;
1402: }
1403: attachmentOM.setData(text);
1404: }
1405:
1406: attachmentOM.setCreatedDate(attachment.getCreatedDate()
1407: .getDate());
1408: final ModifiedDate modifiedDate = attachment.getModifiedDate();
1409: if (modifiedDate != null) {
1410: attachmentOM.setModifiedDate(modifiedDate.getDate());
1411: }
1412: final ScarabUser creUser = findUser(attachment.getCreatedBy());
1413: if (creUser != null) {
1414: attachmentOM.setCreatedBy(creUser.getUserId());
1415: }
1416:
1417: final String modifiedBy = attachment.getModifiedBy();
1418: if (modifiedBy != null) {
1419: final ScarabUser modUserOM = findUser(attachment
1420: .getModifiedBy());
1421: if (modUserOM != null) {
1422: attachmentOM.setModifiedBy(modUserOM.getUserId());
1423: }
1424: }
1425:
1426: attachmentOM.setDeleted(attachment.getDeleted());
1427: return attachmentOM;
1428: }
1429:
1430: private Locale getLocale() {
1431: return ScarabConstants.DEFAULT_LOCALE;
1432: }
1433:
1434: private ScarabUser findUser(final String userStr)
1435: throws TorqueException, ScarabException {
1436:
1437: ScarabUser user = ScarabUserManager.getInstance(userStr);
1438: if (user == null && userStr != null && userStr.indexOf("@") < 0) {
1439: LOG.debug("user specified possibly by email address: "
1440: + userStr);
1441: // maybe it's an email not a username
1442: user = ScarabUserManager.getInstanceByEmail(userStr);
1443: LOG.debug("found " + user);
1444: }
1445: return user;
1446: }
1447:
1448: private Module getModuleForIssue(final XmlModule module,
1449: final XmlIssue issue) throws TorqueException {
1450: return issue.hasModuleCode() ? ModuleManager.getInstance(module
1451: .getDomain(), null, issue.getModuleCode())
1452: : ModuleManager.getInstance(module.getDomain(), module
1453: .getName(), module.getCode());
1454: }
1455: }
|