/**
*
* Copyright
* 2009-2015 Jayway Products AB
* 2016-2017 Föreningen Sambruk
*
* Licensed under AGPL, Version 3.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/agpl.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package se.streamsource.streamflow.client.ui.workspace.table;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.TransactionList;
import ca.odell.glazedlists.UniqueList;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.injection.scope.Uses;
import org.qi4j.api.structure.Module;
import org.qi4j.api.value.ValueBuilder;
import se.streamsource.dci.restlet.client.CommandQueryClient;
import se.streamsource.dci.value.link.LinkValue;
import se.streamsource.dci.value.link.LinksValue;
import se.streamsource.dci.value.table.CellValue;
import se.streamsource.dci.value.table.ColumnValue;
import se.streamsource.dci.value.table.RowValue;
import se.streamsource.dci.value.table.TableQuery;
import se.streamsource.dci.value.table.TableValue;
import se.streamsource.streamflow.api.administration.priority.PriorityValue;
import se.streamsource.streamflow.api.workspace.PerspectiveDTO;
import se.streamsource.streamflow.api.workspace.cases.CaseStates;
import se.streamsource.streamflow.client.ui.workspace.cases.CaseTableValue;
import se.streamsource.streamflow.client.util.LinkComparator;
import se.streamsource.streamflow.client.util.Refreshable;
import se.streamsource.streamflow.util.Strings;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import static se.streamsource.streamflow.client.ui.workspace.WorkspaceResources.*;
/**
* Base class for all models that list cases
*/
public class CasesTableModel extends Observable
implements Refreshable
{
@Structure
protected Module module;
@Uses
protected CommandQueryClient client;
BasicEventList<LinkValue> possibleLabels = new BasicEventList<LinkValue>();
BasicEventList<LinkValue> possibleCaseTypes = new BasicEventList<LinkValue>();
BasicEventList<LinkValue> possibleAssignees = new BasicEventList<LinkValue>();
BasicEventList<LinkValue> possibleProjects = new BasicEventList<LinkValue>();
BasicEventList<LinkValue> possibleCreatedBy = new BasicEventList<LinkValue>();
List<String> selectedStatuses = new ArrayList<String>( Arrays.asList( OPEN.name(), ON_HOLD.name(), CLOSED.name() ));
List<String> selectedCaseTypeIds = new ArrayList<String>();
List<String> selectedLabelIds = new ArrayList<String>();
List<String> selectedAssigneeIds = new ArrayList<String>();
List<String> selectedProjectIds = new ArrayList<String>();
List<String> selectedCreatedByIds = new ArrayList<String>();
List<Integer> invisibleColumns = new ArrayList<Integer>();
GroupBy groupBy = GroupBy.none;
SortBy sortBy = SortBy.none;
SortOrder sortOrder = SortOrder.asc;
private PerspectivePeriodModel createdOnModel;
private PerspectivePeriodModel dueOnModel;
public CasesTableModel(@Structure Module module )
{
this.module = module;
createdOnModel = module.objectBuilderFactory().newObjectBuilder(PerspectivePeriodModel.class).use( Period.none ).newInstance();
dueOnModel = module.objectBuilderFactory().newObjectBuilder(PerspectivePeriodModel.class).use( Period.none ).newInstance();
}
protected EventList<CaseTableValue> eventList = new TransactionList<CaseTableValue>(new BasicEventList<CaseTableValue>());
public EventList<CaseTableValue> getEventList()
{
return eventList;
}
public void search( String text )
{
refresh();
}
public void refresh()
{
ValueBuilder<TableQuery> builder = module.valueBuilderFactory().newValueBuilder(TableQuery.class);
String queryString = "select *";
String whereClause = addWhereClauseFromFilter();
String sorting = addSortingFromFilter();
if( !Strings.empty( whereClause ) )
queryString += " where " + whereClause;
if( !Strings.empty( sorting ))
queryString += sorting;
builder.prototype().tq().set( queryString );
TableQuery query = builder.newInstance();
TableValue table = client.query( "cases", TableValue.class, query);
List<CaseTableValue> caseTableValues = caseTableValues( table );
eventList.getReadWriteLock().writeLock().lock();
try
{
if (eventList instanceof TransactionList)
((TransactionList) eventList).beginEvent();
eventList.clear();
eventList.addAll( caseTableValues );
if (eventList instanceof TransactionList)
((TransactionList) eventList).commitEvent();
} finally
{
eventList.getReadWriteLock().writeLock().unlock();
}
setChanged();
notifyObservers();
}
protected List<CaseTableValue> caseTableValues( TableValue table )
{
List<CaseTableValue> caseTableValues = new ArrayList<CaseTableValue>( );
for(RowValue row : table.rows().get())
{
ValueBuilder<CaseTableValue> caseBuilder = module.valueBuilderFactory().newValueBuilder(CaseTableValue.class);
CaseTableValue prototype = caseBuilder.prototype();
List<CellValue> cells = row.c().get();
for (int i = 0; i < table.cols().get().size(); i++)
{
ColumnValue columnValue = table.cols().get().get( i );
CellValue cell = cells.get( i );
if (columnValue.id().get().equals("assigned"))
prototype.assignedTo().set( cell.f().get() );
else if (columnValue.id().get().equals("caseid"))
prototype.caseId().set( cell.f().get() );
else if (columnValue.id().get().equals("casetype"))
prototype.caseType().set(cell.f().get());
else if (columnValue.id().get().equals("creator"))
prototype.createdBy().set(cell.f().get());
else if (columnValue.id().get().equals("created"))
prototype.creationDate().set((Date) cell.v().get());
else if (columnValue.id().get().equals("due"))
prototype.dueOn().set((Date) cell.v().get());
else if (columnValue.id().get().equals("description"))
prototype.description().set(cell.f().get());
else if (columnValue.id().get().equals("hasattachments"))
prototype.hasAttachments().set((Boolean) cell.v().get());
else if (columnValue.id().get().equals("hascontacts"))
prototype.hasContacts().set((Boolean) cell.v().get());
else if (columnValue.id().get().equals("hasconversations"))
prototype.hasConversations().set((Boolean) cell.v().get());
else if (columnValue.id().get().equals("hasunreadconversation"))
prototype.hasUnreadConversation().set((Boolean) cell.v().get());
else if (columnValue.id().get().equals("hassubmittedforms"))
prototype.hasSubmittedForms().set((Boolean) cell.v().get());
else if (columnValue.id().get().equals("hasunreadform"))
prototype.hasUnreadForm().set((Boolean) cell.v().get());
else if (columnValue.id().get().equals("labels"))
{
String json = cell.v().get().toString();
prototype.labels().set(module.valueBuilderFactory().newValueFromJSON(LinksValue.class, json));
}
else if (columnValue.id().get().equals("owner"))
prototype.owner().set(cell.f().get());
else if (columnValue.id().get().equals("parent") && cell.v().get() != null)
prototype.parentCase().set(module.valueBuilderFactory().newValueFromJSON(LinkValue.class, cell.v().get().toString()));
else if (columnValue.id().get().equals("resolution"))
prototype.resolution().set(cell.f().get());
else if (columnValue.id().get().equals("status"))
prototype.status().set( CaseStates.valueOf( cell.v().get().toString() ));
else if (columnValue.id().get().equals("subcases"))
prototype.subcases().set( module.valueBuilderFactory().newValueFromJSON(LinksValue.class, cell.v().get().toString()) );
else if (columnValue.id().get().equals( "href" ))
prototype.href().set( cell.v().get().toString() );
else if( columnValue.id().get().equals( "removed" ))
prototype.removed().set( (Boolean)cell.v().get() );
else if( columnValue.id().get().equals( "priority" ) && cell.v().get() != null )
prototype.priority().set( module.valueBuilderFactory().newValueFromJSON(PriorityValue.class, cell.v().get().toString()) );
else if (columnValue.id().get().equals("unread"))
prototype.unread().set((Boolean) cell.v().get());
}
caseTableValues.add(caseBuilder.newInstance());
}
return caseTableValues;
}
public EventList<LinkValue> getPossibleLabels()
{
LinksValue labels = client.query( "possiblelabels",
LinksValue.class );
possibleLabels.clear();
possibleLabels.addAll(labels.links().get());
return new UniqueList<LinkValue>( possibleLabels, new LinkComparator() );
}
public BasicEventList<LinkValue> getPossibleCaseTypes()
{
LinksValue caseTypes = client.query( "possiblecasetypes",
LinksValue.class );
possibleCaseTypes.clear();
possibleCaseTypes.addAll(caseTypes.links().get());
return possibleCaseTypes;
}
public BasicEventList<LinkValue> getPossibleAssignees()
{
LinksValue assignees = client.query( "possibleassignees",
LinksValue.class );
possibleAssignees.clear();
possibleAssignees.addAll(assignees.links().get());
return possibleAssignees;
}
public BasicEventList<LinkValue> getPossibleProjects()
{
LinksValue projects = client.query( "possibleprojects",
LinksValue.class );
possibleProjects.clear();
possibleProjects.addAll((Collection)projects.links().get());
return possibleProjects;
}
public BasicEventList<LinkValue> getPossibleCreatedBy()
{
LinksValue createdby = client.query( "possiblecreatedby",
LinksValue.class );
possibleCreatedBy.clear();
possibleCreatedBy.addAll(createdby.links().get());
return possibleCreatedBy;
}
public List<String> getSelectedStatuses()
{
return selectedStatuses;
}
public List<String> getSelectedCaseTypes()
{
return selectedDescriptions( selectedCaseTypeIds, possibleCaseTypes );
}
public List<String> getSelectedCaseTypeIds()
{
return selectedCaseTypeIds;
}
public List<String> getSelectedLabels()
{
return selectedDescriptions( selectedLabelIds, possibleLabels );
}
public List<String> getSelectedLabelIds()
{
return selectedLabelIds;
}
public List<String> getSelectedAssignees()
{
return selectedDescriptions( selectedAssigneeIds, possibleAssignees );
}
public List<String> getSelectedAssigneeIds()
{
return selectedAssigneeIds;
}
public List<String> getSelectedProjects()
{
return selectedDescriptions( selectedProjectIds, possibleProjects );
}
public List<String> getSelectedProjectIds()
{
return selectedProjectIds;
}
public List<String> getSelectedCreatedBy()
{
return selectedDescriptions( selectedCreatedByIds, possibleCreatedBy );
}
public List<String> getSelectedCreatedByIds()
{
return selectedCreatedByIds;
}
public GroupBy getGroupBy()
{
return groupBy;
}
public void setGroupBy( GroupBy groupBy )
{
this.groupBy = groupBy;
}
public SortBy getSortBy()
{
return sortBy;
}
public void setSortBy( SortBy sortBy )
{
this.sortBy = sortBy;
}
public SortOrder getSortOrder()
{
return sortOrder;
}
public void setSortOrder( SortOrder sortOrder )
{
this.sortOrder = sortOrder;
}
public PerspectivePeriodModel getCreatedOnModel()
{
return createdOnModel;
}
public PerspectivePeriodModel getDueOnModel()
{
return dueOnModel;
}
public PerspectiveDTO getPerspective(String name, String query)
{
ValueBuilder<PerspectiveDTO> builder = module.valueBuilderFactory().newValueBuilder(PerspectiveDTO.class);
builder.prototype().query().set( query );
builder.prototype().name().set( name );
builder.prototype().labels().set( selectedLabelIds );
builder.prototype().statuses().set( selectedStatuses );
builder.prototype().sortBy().set( sortBy.name() );
builder.prototype().sortOrder().set( sortOrder.name() );
builder.prototype().groupBy().set( groupBy.name() );
builder.prototype().assignees().set( selectedAssigneeIds );
builder.prototype().caseTypes().set( selectedCaseTypeIds );
builder.prototype().createdBy().set( selectedCreatedByIds );
builder.prototype().projects().set( selectedProjectIds );
builder.prototype().createdOnPeriod().set( createdOnModel.getPeriod().name() );
builder.prototype().createdOn().set( createdOnModel.getDate() );
builder.prototype().dueOnPeriod().set( dueOnModel.getPeriod().name() );
builder.prototype().dueOn().set( dueOnModel.getDate() );
//TODO Can refernce be made relative
builder.prototype().context().set( client.getReference().toString() );
builder.prototype().invisibleColumns().set( invisibleColumns );
return builder.newInstance();
}
public void clearFilter()
{
selectedStatuses = new ArrayList<String>();
selectedCaseTypeIds = new ArrayList<String>();
selectedLabelIds = new ArrayList<String>();
selectedAssigneeIds = new ArrayList<String>();
selectedProjectIds = new ArrayList<String>();
selectedCreatedByIds = new ArrayList<String>();
invisibleColumns = new ArrayList<Integer>();
groupBy = GroupBy.none;
sortBy = SortBy.none;
sortOrder = SortOrder.asc;
createdOnModel.setDate( null );
createdOnModel.setPeriod( Period.none );
dueOnModel.setDate( null );
dueOnModel.setPeriod( Period.none );
}
public List<LinkValue> possibleFilterLinks()
{
return client.query().queries().get();
}
public void setFilter(PerspectiveDTO perspectiveDTO)
{
perspectiveDTO = module.valueBuilderFactory().newValueBuilder(PerspectiveDTO.class).withPrototype(perspectiveDTO).prototype();
selectedStatuses = perspectiveDTO.statuses().get();
selectedCaseTypeIds = perspectiveDTO.caseTypes().get();
selectedLabelIds = perspectiveDTO.labels().get();
selectedAssigneeIds = perspectiveDTO.assignees().get();
selectedProjectIds = perspectiveDTO.projects().get();
selectedCreatedByIds = perspectiveDTO.createdBy().get();
sortBy = SortBy.valueOf( perspectiveDTO.sortBy().get() );
sortOrder = SortOrder.valueOf( perspectiveDTO.sortOrder().get() );
groupBy = GroupBy.valueOf( perspectiveDTO.groupBy().get() );
createdOnModel.setPeriod( Period.valueOf( perspectiveDTO.createdOnPeriod().get() ) );
createdOnModel.setDate( perspectiveDTO.createdOn().get() );
dueOnModel.setPeriod( Period.valueOf( perspectiveDTO.dueOnPeriod().get() ) );
dueOnModel.setDate( perspectiveDTO.dueOn().get() );
invisibleColumns = perspectiveDTO.invisibleColumns().get();
}
protected String addSortingFromFilter()
{
String sort = "";
if (sortBy != SortBy.none)
{
sort = " order by " + sortBy.name() + " " + sortOrder.name();
}
return sort;
}
protected String addWhereClauseFromFilter()
{
String filter = "";
if (!selectedStatuses.isEmpty())
{
filter += " status:";
String comma = "";
for ( String status : selectedStatuses )
{
filter += comma + status;
comma = ",";
}
}
if (!selectedCaseTypeIds.isEmpty())
{
filter += " caseType:\"";
String comma = "";
for (String caseType : selectedCaseTypeIds)
{
filter += comma + caseType;
comma = ",";
}
filter += "\"";
}
if (!selectedLabelIds.isEmpty())
{
filter += " label:\"";
String comma = "";
for (String label : selectedLabelIds)
{
filter += comma + label;
comma = ",";
}
filter += "\"";
}
if (!selectedAssigneeIds.isEmpty())
{
filter += " assignedTo:\"";
String comma = "";
for (String assignee : selectedAssigneeIds)
{
filter += comma + assignee;
comma = ",";
}
filter += "\"";
}
if (!selectedProjectIds.isEmpty())
{
filter += " project:\"";
String comma = "";
for (String project : selectedProjectIds)
{
filter += comma + project;
comma = ",";
}
filter += "\"";
}
if (!selectedCreatedByIds.isEmpty())
{
filter += " createdBy:\"";
String comma = "";
for (String createdBy : selectedCreatedByIds)
{
filter += comma + createdBy;
comma = ",";
}
filter += "\"";
}
if ( !Period.none.equals( createdOnModel.getPeriod() ) )
{
filter += " createdOn:" + createdOnModel.getSearchValue( "yyyyMMdd", "-" );
}
if( !Period.none.equals( dueOnModel.getPeriod() ))
{
filter += " dueOn:" + dueOnModel.getSearchValue( "yyyyMMdd", "-" );
}
return filter;
}
private List<String> selectedDescriptions( List<String> selected, List<LinkValue> baseList )
{
List<String> descriptions = new ArrayList<String>();
for(String id : selected )
{
for( LinkValue link : baseList )
{
if( link.id().get().equals( id ))
descriptions.add( link.text().get() );
}
}
return descriptions;
}
public List<Integer> getInvisibleColumns()
{
return invisibleColumns;
}
public void addInvisibleColumn( Integer index )
{
if( !invisibleColumns.contains( index ) )
{
invisibleColumns.add( index );
}
}
public void removeInvisibleColumn( Integer index )
{
invisibleColumns.remove( index );
}
public void createCase()
{
client.postCommand( "createcase" );
}
public boolean isCreateCaseEnabled()
{
return client.getReference().getLastSegment().equals("assignments") || client.getReference().getLastSegment().equals("drafts");
}
public boolean containsCaseWithPriority()
{
for(CaseTableValue value : getEventList() )
{
if( value.priority().get() != null )
{
return true;
}
}
return false;
}
}