/*
* HeadsUp Agile
* Copyright 2009-2014 Heads Up Development Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.headsupdev.agile.app.issues;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.*;
import org.apache.wicket.markup.html.CSSPackageResource;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.CompoundPropertyModel;
import org.headsupdev.agile.api.Permission;
import org.headsupdev.agile.api.Project;
import org.headsupdev.agile.app.issues.permission.IssueEditPermission;
import org.headsupdev.agile.storage.HibernateStorage;
import org.headsupdev.agile.storage.dao.IssuesDAO;
import org.headsupdev.agile.storage.issues.Issue;
import org.headsupdev.agile.storage.issues.IssueRelationship;
import org.headsupdev.agile.web.BookmarkableMenuLink;
import org.headsupdev.agile.web.HeadsUpPage;
import org.headsupdev.agile.web.MountPoint;
import org.headsupdev.agile.web.components.OnePressSubmitButton;
import org.headsupdev.agile.web.components.ProjectTreeDropDownChoice;
import org.headsupdev.agile.web.components.issues.IssueUtils;
import org.hibernate.criterion.Restrictions;
import java.util.Date;
import java.util.Iterator;
/**
* Add a relationship for an issue
*
* @author Andrew Williams
* @version $Id$
* @since 1.0
*/
@MountPoint("relate")
public class CreateRelationship
extends HeadsUpPage
{
private Issue issue;
private IssuesDAO dao;
public Permission getRequiredPermission()
{
return new IssueEditPermission();
}
public void layout()
{
super.layout();
add( CSSPackageResource.getHeaderContribution( getClass(), "issue.css" ) );
long id;
try
{
id = getPageParameters().getLong( "id" );
}
catch ( NumberFormatException e )
{
notFoundError();
return;
}
Issue issue = IssuesApplication.getIssue( id, getProject() );
if ( issue == null )
{
notFoundError();
return;
}
this.dao = new IssuesDAO();
addLink( new BookmarkableMenuLink( getPageClass( "issues/view" ), getPageParameters(), "view" ) );
this.issue = issue;
add( new RelationshipForm( "relationship" ) );
}
class RelationshipForm
extends Form
{
private Project relatedProject = issue.getProject();
private String relatedIssueText;
private int type = IssueRelationship.TYPE_LINKED;
public RelationshipForm( String id )
{
super( id );
setModel( new CompoundPropertyModel( this ) );
add( new IssueSubheader( "subHeader", "Create Relationship for ", issue ) );
add( new ProjectTreeDropDownChoice( "relatedProject" )
{
@Override
protected boolean wantOnSelectionChangedNotifications()
{
return true;
}
} );
add( new AutoCompleteTextField<Issue>( "relatedIssueText" )
{
@Override
protected AutoCompleteBehavior<Issue> newAutoCompleteBehavior( IAutoCompleteRenderer<Issue> renderer,
AutoCompleteSettings settings )
{
return super.newAutoCompleteBehavior( new AbstractAutoCompleteTextRenderer<Issue>()
{
@Override
protected String getTextValue( Issue issue )
{
return issue.getId() + ": " + issue.getSummary();
}
}, settings );
}
@Override
protected Iterator<Issue> getChoices( String text )
{
String searchText = "%" + text + "%";
long maybeId = 0;
try
{
maybeId = Long.parseLong( text );
}
catch ( NumberFormatException e )
{
// ignore
}
return dao.search( Restrictions.or( Restrictions.eq( "id.id", maybeId ),
Restrictions.like( "summary", searchText ) ), relatedProject ).iterator();
}
} );
add( new DropDownChoice( "type", IssueUtils.getRelationships() ).setChoiceRenderer( new ChoiceRenderer()
{
public Object getDisplayValue( Object o )
{
return IssueUtils.getRelationshipName( (Integer) o );
}
} ) );
add( new OnePressSubmitButton( "submitRelationship" ) );
}
public void onSubmit()
{
issue = (Issue) ( (HibernateStorage) getStorage() ).getHibernateSession().merge( issue );
long relatedIssueId = getIdFromAutocomplete( relatedIssueText );
Issue related = IssuesApplication.getIssue( relatedIssueId, relatedProject );
if ( related == null )
{
error( "Could not find issue " + relatedIssueText + " in project " + relatedProject );
return;
}
if ( related.equals( issue ) )
{
error( "Cannot relate to the current issue" );
return;
}
IssueRelationship relationship = new IssueRelationship( issue, related, type );
if ( issue.hasRelationship( relationship ) )
{
error( "Cannot add a duplicate relationship" );
return;
}
if ( type > IssueRelationship.REVERSE_RELATIONSHIP )
{
relationship = relationship.getInverseRelationship();
( (HibernateStorage) getStorage() ).save( relationship );
related.getRelationships().add( relationship );
}
else
{
( (HibernateStorage) getStorage() ).save( relationship );
issue.getRelationships().add( ( relationship ) );
}
issue.setUpdated( new Date() );
setResponsePage( getPageClass( "issues/view" ), getPageParameters() );
}
}
protected long getIdFromAutocomplete( String autocompleteText )
{
if ( autocompleteText == null )
{
return 0;
}
int colonPos = autocompleteText.indexOf( ':' );
String idString;
if ( colonPos == -1 )
{
idString = autocompleteText;
}
else
{
idString = autocompleteText.substring( 0, colonPos );
}
try
{
return Long.parseLong( idString );
}
catch ( NumberFormatException e )
{
return 0;
}
}
@Override
public String getPageTitle()
{
return "Create Relationship for Issue:" + issue.getId() + PAGE_TITLE_SEPARATOR + getAppProductTitle();
}
}