/* ===========================================================================
* Copyright (c) 2007 Serena Software. All rights reserved.
*
* Use of the Sample Code provided by Serena is governed by the following
* terms and conditions. By using the Sample Code, you agree to be bound by
* the terms contained herein. If you do not agree to the terms herein, do
* not install, copy, or use the Sample Code.
*
* 1. GRANT OF LICENSE. Subject to the terms and conditions herein, you
* shall have the nonexclusive, nontransferable right to use the Sample Code
* for the sole purpose of developing applications for use solely with the
* Serena software product(s) that you have licensed separately from Serena.
* Such applications shall be for your internal use only. You further agree
* that you will not: (a) sell, market, or distribute any copies of the
* Sample Code or any derivatives or components thereof; (b) use the Sample
* Code or any derivatives thereof for any commercial purpose; or (c) assign
* or transfer rights to the Sample Code or any derivatives thereof.
*
* 2. DISCLAIMER OF WARRANTIES. TO THE MAXIMUM EXTENT PERMITTED BY
* APPLICABLE LAW, SERENA PROVIDES THE SAMPLE CODE AS IS AND WITH ALL
* FAULTS, AND HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER
* EXPRESSED, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY
* IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A
* PARTICULAR PURPOSE, OF LACK OF VIRUSES, OF RESULTS, AND OF LACK OF
* NEGLIGENCE OR LACK OF WORKMANLIKE EFFORT, CONDITION OF TITLE, QUIET
* ENJOYMENT, OR NON-INFRINGEMENT. THE ENTIRE RISK AS TO THE QUALITY OF
* OR ARISING OUT OF USE OR PERFORMANCE OF THE SAMPLE CODE, IF ANY,
* REMAINS WITH YOU.
*
* 3. EXCLUSION OF DAMAGES. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE
* LAW, YOU AGREE THAT IN CONSIDERATION FOR RECEIVING THE SAMPLE CODE AT NO
* CHARGE TO YOU, SERENA SHALL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER,
* INCLUDING BUT NOT LIMITED TO DIRECT, SPECIAL, INCIDENTAL, INDIRECT, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF
* PROFITS OR CONFIDENTIAL OR OTHER INFORMATION, FOR BUSINESS INTERRUPTION,
* FOR PERSONAL INJURY, FOR LOSS OF PRIVACY, FOR NEGLIGENCE, AND FOR ANY
* OTHER LOSS WHATSOEVER) ARISING OUT OF OR IN ANY WAY RELATED TO THE USE
* OF OR INABILITY TO USE THE SAMPLE CODE, EVEN IN THE EVENT OF THE FAULT,
* TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY, OR BREACH OF CONTRACT,
* EVEN IF SERENA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE
* FOREGOING LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SHALL APPLY TO THE
* MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. NOTWITHSTANDING THE ABOVE,
* IN NO EVENT SHALL SERENA'S LIABILITY UNDER THIS AGREEMENT OR WITH RESPECT
* TO YOUR USE OF THE SAMPLE CODE AND DERIVATIVES THEREOF EXCEED US$10.00.
*
* 4. INDEMNIFICATION. You hereby agree to defend, indemnify and hold
* harmless Serena from and against any and all liability, loss or claim
* arising from this agreement or from (i) your license of, use of or
* reliance upon the Sample Code or any related documentation or materials,
* or (ii) your development, use or reliance upon any application or
* derivative work created from the Sample Code.
*
* 5. TERMINATION OF THE LICENSE. This agreement and the underlying
* license granted hereby shall terminate if and when your license to the
* applicable Serena software product terminates or if you breach any terms
* and conditions of this agreement.
*
* 6. CONFIDENTIALITY. The Sample Code and all information relating to the
* Sample Code (collectively "Confidential Information") are the
* confidential information of Serena. You agree to maintain the
* Confidential Information in strict confidence for Serena. You agree not
* to disclose or duplicate, nor allow to be disclosed or duplicated, any
* Confidential Information, in whole or in part, except as permitted in
* this Agreement. You shall take all reasonable steps necessary to ensure
* that the Confidential Information is not made available or disclosed by
* you or by your employees to any other person, firm, or corporation. You
* agree that all authorized persons having access to the Confidential
* Information shall observe and perform under this nondisclosure covenant.
* You agree to immediately notify Serena of any unauthorized access to or
* possession of the Confidential Information.
*
* 7. AFFILIATES. Serena as used herein shall refer to Serena Software,
* Inc. and its affiliates. An entity shall be considered to be an
* affiliate of Serena if it is an entity that controls, is controlled by,
* or is under common control with Serena.
*
* 8. GENERAL. Title and full ownership rights to the Sample Code,
* including any derivative works shall remain with Serena. If a court of
* competent jurisdiction holds any provision of this agreement illegal or
* otherwise unenforceable, that provision shall be severed and the
* remainder of the agreement shall remain in full force and effect.
* ===========================================================================
*/
/**
** @brief This experimental plugin extends Hudson support for Dimensions SCM repositories
**
** @author Tim Payne
**
**/
package hudson.plugins.dimensionsscm;
import hudson.plugins.dimensionsscm.Logger;
import hudson.plugins.dimensionsscm.DateUtils;
import com.serena.dmclient.api.DimensionsRuntimeException;
import hudson.model.User;
import hudson.scm.ChangeLogSet;
import hudson.scm.EditType;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.text.Collator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
/**
* Represents a change set.
*/
@ExportedBean(defaultVisibility=999)
public class DimensionsChangeSet extends ChangeLogSet.Entry
{
private String developer;
private String message;
private String identifier;
private Calendar date;
private String version;
private Collection<DmFiles> items = new HashSet<DmFiles>();
private Collection<DmRequests> requests = new HashSet<DmRequests>();
// Digester class seems to need a default or null constructor else it crashes
public DimensionsChangeSet() {
this("","","","","","",null);
}
/*
* Default constructor for a changeset
* @param String file
* @param String developer
* @param String op
* @param String revision
* @param String comment
* @param String url
* @param Calendar date
*/
public DimensionsChangeSet(String file, String developer, String op,
String revision, String comment, String url, Calendar date) {
this.identifier = file;
this.developer = developer;
this.message = comment;
this.date = date;
this.version = revision;
this.items = new HashSet<DmFiles>();
this.items.add(new DmFiles(file,op,url));
this.requests = new HashSet<DmRequests>();
}
public void setParent(ChangeLogSet parent) {
super.setParent(parent);
}
public Date getDate() {
return this.date.getTime();
}
public String getDeveloper() {
return this.developer;
}
public String getSCMComment() {
return this.message;
}
public void setDateString(String DateString) throws ParseException {
date = Calendar.getInstance();
TimeZone tz = TimeZone.getTimeZone("UTC");
date.setTime(DateUtils.parse(DateString,tz));
}
public Collection<DmFiles> getFiles() {
return this.items;
}
public Collection<DmRequests> getRequests() {
return this.requests;
}
@Override
public Collection<String> getAffectedPaths() {
Collection<String> paths = new ArrayList<String>(items.size());
for (DmFiles item : items) {
paths.add(item.getFile());
}
return paths;
}
@Override
public User getAuthor() {
if (this.developer == null)
throw new RuntimeException("No author in this changeset!");
return User.get(this.developer, true);
}
@Override
public String getMsg() {
return this.message;
}
public String getId() {
return this.identifier;
}
public void setVersion(String x) {
this.version = x;
}
public String getVersion() {
return this.version;
}
public void setUser(String x) {
this.developer = x;
}
public String getUser() {
return this.developer;
}
public void setComment(String x) {
this.message = x;
}
public String getComment() {
return getSCMComment();
}
public void add(DimensionsChangeSet.DmFiles file) {
items.add(file);
file.setParent(this);
}
public void add(String file, String operation, String url) {
DimensionsChangeSet.DmFiles x = new DmFiles(file,operation,url);
items.add(x);
x.setParent(this);
}
public void addRequest(DimensionsChangeSet.DmRequests newreq) {
for (DmRequests req : requests) {
if (req.getIdentifier().equals(newreq.getIdentifier())) return;
}
requests.add(newreq);
newreq.setParent(this);
}
public void addRequest(String objectId, String url) {
for (DmRequests req : requests) {
if (req.getIdentifier().equals(objectId)) return;
}
DimensionsChangeSet.DmRequests x = new DmRequests(objectId,url);
requests.add(x);
x.setParent(this);
}
public void addRequest(String objectId, String url, String title) {
for (DmRequests req : requests) {
if (req.getIdentifier().equals(objectId)) return;
}
DimensionsChangeSet.DmRequests x = new DmRequests(objectId,url,title);
requests.add(x);
x.setParent(this);
}
/*
* List of changes made in the repository for this changeset
*/
@ExportedBean(defaultVisibility=999)
public static class DmFiles
{
private String fileName;
private String operation;
private String url;
private DimensionsChangeSet parent;
public DmFiles() {
this("","","");
}
public DmFiles(String fileName, String operation, String url) {
this.fileName = fileName;
this.url = url;
this.operation = operation;
}
@Exported
public String getUrl() {
if (this.url.length() == 0)
return null;
else
return this.url;
}
@Exported
public String getOperation() {
return this.operation;
}
@Exported
public String getFile() {
if (this.fileName.length() == 0)
return null;
else
return this.fileName;
}
public DimensionsChangeSet getParent() {
return this.parent;
}
@Exported
public EditType getEditType() {
if (operation.equalsIgnoreCase("delete")) {
return EditType.DELETE;
} else
if (operation.equalsIgnoreCase("add")) {
return EditType.ADD;
} else
return EditType.EDIT;
}
public void setUrl(String url) {
this.url = url;
}
public void setOperation(String operation) {
this.operation = operation;
}
public void setFile(String fileName) {
this.fileName = fileName;
}
public void setParent(DimensionsChangeSet parent) {
this.parent = parent;
}
}
@ExportedBean(defaultVisibility=999)
public static class DmRequests {
private String identifier;
private String url;
private String title;
private DimensionsChangeSet parent;
public DmRequests() {
this("","","");
}
public DmRequests(String objectID, String url) {
this.identifier = objectID;
this.url = url;
this.title = "";
}
public DmRequests(String objectID, String url, String title) {
this.identifier = objectID;
this.url = url;
this.title = title;
}
@Exported
public String getUrl() {
if (this.url == null || this.url.length() == 0)
return null;
else
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
@Exported
public String getIdentifier() {
if (this.identifier == null || this.identifier.length() == 0)
return null;
else
return this.identifier;
}
public void setIdentifier(String id) {
this.identifier = id;
}
@Exported
public String getTitle() {
if (this.title == null || this.title.length() == 0)
return null;
else
return this.title;
}
public void setTitle(String id) {
this.title = id;
}
public void setParent(DimensionsChangeSet parent) {
this.parent = parent;
}
}
}