/**
*
* 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.web.application.statistics;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Test;
import org.qi4j.api.unitofwork.UnitOfWork;
import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
import org.qi4j.bootstrap.AssemblyException;
import org.qi4j.bootstrap.ImportedServiceDeclaration;
import org.qi4j.bootstrap.ModuleAssembly;
import org.qi4j.entitystore.memory.MemoryEntityStoreService;
import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
import org.qi4j.test.AbstractQi4jTest;
import se.streamsource.dci.api.RoleMap;
import se.streamsource.infrastructure.index.elasticsearch.ElasticSearchConfiguration;
import se.streamsource.infrastructure.index.elasticsearch.assembly.ESMemoryIndexQueryAssembler;
import se.streamsource.streamflow.api.administration.priority.PriorityValue;
import se.streamsource.streamflow.api.workspace.cases.caselog.CaseLogEntryDTO;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactDTO;
import se.streamsource.streamflow.infrastructure.configuration.FileConfiguration;
import se.streamsource.streamflow.infrastructure.event.domain.DomainEvent;
import se.streamsource.streamflow.infrastructure.event.domain.TransactionDomainEvents;
import se.streamsource.streamflow.infrastructure.event.domain.factory.DomainEventFactoryService;
import se.streamsource.streamflow.infrastructure.event.domain.source.helper.TransactionTrackerConfiguration;
import se.streamsource.streamflow.infrastructure.time.TimeService;
import se.streamsource.streamflow.web.application.security.UserPrincipal;
import se.streamsource.streamflow.web.configuration.ServiceConfiguration;
import se.streamsource.streamflow.web.context.administration.GroupsContext;
import se.streamsource.streamflow.web.domain.entity.attachment.AttachmentEntity;
import se.streamsource.streamflow.web.domain.entity.caselog.CaseLogEntity;
import se.streamsource.streamflow.web.domain.entity.casetype.CaseTypeEntity;
import se.streamsource.streamflow.web.domain.entity.casetype.ResolutionEntity;
import se.streamsource.streamflow.web.domain.entity.caze.CaseEntity;
import se.streamsource.streamflow.web.domain.entity.conversation.ConversationEntity;
import se.streamsource.streamflow.web.domain.entity.conversation.MessageEntity;
import se.streamsource.streamflow.web.domain.entity.label.LabelEntity;
import se.streamsource.streamflow.web.domain.entity.note.NotesTimeLineEntity;
import se.streamsource.streamflow.web.domain.entity.organization.*;
import se.streamsource.streamflow.web.domain.entity.project.ProjectEntity;
import se.streamsource.streamflow.web.domain.entity.user.UserEntity;
import se.streamsource.streamflow.web.domain.entity.user.UsersEntity;
import se.streamsource.streamflow.web.domain.structure.caselog.CaseLogEntryValue;
import se.streamsource.streamflow.web.domain.structure.casetype.Resolution;
import se.streamsource.streamflow.web.domain.structure.group.Group;
import se.streamsource.streamflow.web.domain.structure.label.Label;
import se.streamsource.streamflow.web.domain.structure.note.NoteValue;
import se.streamsource.streamflow.web.domain.structure.organization.Organization;
import se.streamsource.streamflow.web.domain.structure.organization.OrganizationalUnit;
import se.streamsource.streamflow.web.domain.structure.organization.Organizations;
import se.streamsource.streamflow.web.domain.structure.organization.ParticipantRolesValue;
import se.streamsource.streamflow.web.domain.structure.project.Project;
import se.streamsource.streamflow.web.domain.structure.user.Users;
import se.streamsource.streamflow.web.infrastructure.event.MemoryEventStoreService;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/**
* JAVADOC
*/
public class CaseStatisticsServiceTest
extends AbstractQi4jTest
{
public void assemble(ModuleAssembly module) throws AssemblyException
{
module.services(MemoryEntityStoreService.class, FileConfiguration.class);
module.services( CaseStatisticsService.class,
MemoryEventStoreService.class,
UuidIdentityGeneratorService.class,
LoggingStatisticsStore.class ).instantiateOnStartup();
module.importedServices( TimeService.class ).importedBy( ImportedServiceDeclaration.NEW_OBJECT );
module.services( DomainEventFactoryService.class ).instantiateOnStartup();
module.entities(StatisticsConfiguration.class);
module.forMixin(TransactionTrackerConfiguration.class).declareDefaults().enabled().set(true);
module.entities(LabelEntity.class,
OrganizationsEntity.class,
OrganizationEntity.class,
OrganizationalUnitEntity.class,
ProjectEntity.class,
GroupEntity.class,
UsersEntity.class,
RoleEntity.class,
UserEntity.class,
NotesTimeLineEntity.class,
ResolutionEntity.class,
CaseEntity.class,
CaseTypeEntity.class,
ConversationEntity.class,
MessageEntity.class,
AttachmentEntity.class,
CaseLogEntity.class,
PriorityEntity.class,
GlobalCaseIdStateEntity.class);
module.values(ContactDTO.class, ParticipantRolesValue.class, CaseLogEntryDTO.class, NoteValue.class, CaseLogEntryValue.class, PriorityValue.class );
module.objects(TimeService.class, CaseStatisticsServiceTest.class);
module.transients(GroupsContext.class);
module.values(DomainEvent.class, TransactionDomainEvents.class);
module.values(CaseStatisticsValue.class, FormFieldStatisticsValue.class, RelatedStatisticsValue.class, OrganizationalStructureValue.class, OrganizationalUnitValue.class);
}
@Test
public void testLabelChangeDescription() throws UnitOfWorkCompletionException, InterruptedException
{
TestAppender appender = new TestAppender();
Logger.getRootLogger().addAppender(appender);
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
LabelEntity label1 = uow.newEntity(LabelEntity.class, "label1");
label1.changeDescription("Foo bar");
uow.complete();
Thread.sleep(1000);
assertThat(appender.getEvents().get(0).getMessage().toString(), equalTo("id:label1, description:Foo bar, type:label"));
}
@Test
public void testCaseClosedAndRemoved() throws UnitOfWorkCompletionException, PrivilegedActionException, InterruptedException
{
TestAppender appender = new TestAppender();
Logger.getRootLogger().addAppender(appender);
Logger.getRootLogger().setLevel(Level.DEBUG);
final UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
Users users = uow.newEntity(UsersEntity.class, UsersEntity.USERS_ID);
final UserEntity user1 = (UserEntity) users.createUser("user1", "userpwd");
RoleMap.newCurrentRoleMap();
RoleMap.current().set(new UserPrincipal(user1.userName().get()));
RoleMap.current().set(user1);
final String[] id = new String[1];
Organizations orgs = uow.newEntity(Organizations.class, OrganizationsEntity.ORGANIZATIONS_ID);
Organization org = orgs.createOrganization("Organization1");
OrganizationalUnit ou1 = org.createOrganizationalUnit("OU1");
uow.newEntity( GlobalCaseIdStateEntity.class, GlobalCaseIdStateEntity.GLOBALCASEIDSTATE_ID );
Group group1 = ou1.createGroup( "Group1" );
group1.addParticipant( user1 );
//Group group1 = moduleInstance.transientBuilderFactory().newTransientBuilder(GroupsContext.class).use(ou1).newInstance().create("Group1");
//group1.addParticipant(user1);
Project project1 = ou1.createProject("Project1");
project1.addMember(group1);
CaseTypeEntity caseType1 = (CaseTypeEntity) project1.createCaseType("Casetype");
caseType1.changeDescription("Casetype");
Resolution fixed = caseType1.createResolution("Fixed");
Label label1 = caseType1.createLabel("Label1");
uow.complete();
UnitOfWork caseUoW = unitOfWorkFactory.newUnitOfWork();
UserEntity user = caseUoW.get(user1);
caseType1 = caseUoW.get(caseType1);
project1 = caseUoW.get(project1);
fixed = caseUoW.get(fixed);
label1 = caseUoW.get(label1);
//RoleMap.current().set( user1, null );
RoleMap.current().set( user );
CaseEntity case1 = user.createDraft();
case1.changeDescription("Case description");
case1.addNote( "Case note", "text/plain" );
case1.addLabel(label1);
case1.changeCaseType(caseType1);
case1.changeOwner(project1);
case1.open();
case1.assignTo(user);
case1.resolve(fixed);
case1.close();
id[0] = case1.identity().get();
caseUoW.complete();
Thread.sleep(1000);
// Verify log records
int idx = 0;
assertThat(appender.getEvents().get(idx).getMessage().toString(), new ContainsMatcher("description:Organization1, type:organization"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("New organizational structure:"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:OU1, type:organizationalUnit"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:Group1, type:group"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:Project1"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:Casetype"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:Fixed"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:Label1"));
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("description:Case description"));
UnitOfWork removeUoW = unitOfWorkFactory.newUnitOfWork();
case1 = removeUoW.get(CaseEntity.class, id[0]);
case1.deleteEntity();
removeUoW.complete();
Thread.sleep(1000);
assertThat(appender.getEvents().get(++idx).getMessage().toString(), new ContainsMatcher("Marked statistics for"));
}
public static class TestAppender
extends AppenderSkeleton
{
List<LoggingEvent> events = new ArrayList<LoggingEvent>();
@Override
protected void append(LoggingEvent event)
{
if (event.getLevel().isGreaterOrEqual(Level.DEBUG))
events.add(event);
}
public boolean requiresLayout()
{
return false;
}
public void close()
{
}
public List<LoggingEvent> getEvents()
{
return events;
}
}
public static class RegularMatcher
extends BaseMatcher
{
String regex;
public RegularMatcher(String regex)
{
this.regex = regex;
}
public boolean matches(Object o)
{
return Pattern.matches(regex, o.toString());
}
public void describeTo(Description description)
{
description.appendText("Blah");
}
}
public static class ContainsMatcher
extends BaseMatcher
{
String str;
public ContainsMatcher(String str)
{
this.str = str;
}
public boolean matches(Object o)
{
return o.toString().contains(str);
}
public void describeTo(Description description)
{
description.appendText(str);
}
}
}