/** * * 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.rest.resource.events; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import org.qi4j.api.injection.scope.Service; import org.qi4j.api.service.qualifier.Tagged; import org.qi4j.api.util.DateFunctions; import org.restlet.data.CharacterSet; import org.restlet.data.MediaType; import org.restlet.data.Status; import org.restlet.ext.atom.Content; import org.restlet.ext.atom.Entry; import org.restlet.ext.atom.Feed; import org.restlet.ext.atom.Text; import org.restlet.representation.Representation; import org.restlet.representation.StringRepresentation; import org.restlet.representation.Variant; import org.restlet.representation.WriterRepresentation; import org.restlet.resource.ResourceException; import org.restlet.resource.ServerResource; import se.streamsource.streamflow.infrastructure.event.domain.DomainEvent; import se.streamsource.streamflow.infrastructure.event.domain.TransactionDomainEvents; import se.streamsource.streamflow.infrastructure.event.domain.source.EventSource; import se.streamsource.streamflow.infrastructure.event.domain.source.TransactionVisitor; /** * Get events before or after a given date in various formats */ public class DomainEventsServerResource extends ServerResource { @Service @Tagged("domain") EventSource source; public DomainEventsServerResource() { getVariants().add(new Variant( MediaType.TEXT_HTML)); getVariants().add(new Variant( MediaType.APPLICATION_ATOM)); getVariants().add(new Variant( MediaType.APPLICATION_JSON)); } @Override protected Representation get( Variant variant ) throws ResourceException { String before = null; String after = getRequest().getResourceRef().getQueryAsForm().getFirstValue( "after" ); final List<TransactionDomainEvents> transactionDomains = new ArrayList<TransactionDomainEvents>( ); // Get transactionDomains first if (after != null) { final long afterDate = Long.parseLong( after ); source.transactionsAfter( afterDate, new RESTTransactionVisitor( transactionDomains ) ); } else { before = getRequest().getResourceRef().getQueryAsForm().getFirstValue( "before" ); final long beforeDate = before == null ? System.currentTimeMillis() : Long.parseLong( before ); source.transactionsBefore( beforeDate, new RESTTransactionVisitor( transactionDomains ) ); // Reverse list Collections.reverse( transactionDomains ); } if (variant.getMediaType().equals( MediaType.TEXT_HTML )) { WriterRepresentation representation = new WriterRepresentation( MediaType.TEXT_HTML ) { public void write( final Writer writer ) throws IOException { String earlier = transactionDomains.size() == 0 ? System.currentTimeMillis()+"" : transactionDomains.get( 0 ).timestamp().get().toString(); String later = transactionDomains.size() == 0 ? System.currentTimeMillis()+"" : transactionDomains.get( transactionDomains.size()-1).timestamp().get().toString(); writer.append( "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "<head>\n" + " <title>Domain events</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<a href=\"?before="+earlier+"\">Earlier</a> | \n" + "<a href=\"?after="+later+"\">Later</a>\n" + "<table style=\"font-size:10\" border=\"1\" cellpadding=\"0\">\n" + " <tr>\n" + " <th>Usecase</th>\n" + " <th>Event</th>\n" + " <th>Timestamp</th>\n" + " <th>Entity</th>\n" + " <th>Parameters</th>\n" + " <th>User</th>\n" + " </tr>\n"); for (TransactionDomainEvents transaction : transactionDomains) { for (DomainEvent domainEvent : transaction.events().get()) { writer.append( "<tr><td>" ).append( domainEvent.usecase().get() ). append("</td><td>").append( domainEvent.name().get() ). append("</td><td>").append( DateFunctions.toUtcString( domainEvent.on().get()) ). append("</td><td>").append( domainEvent.entity().get() ). append("</td><td>").append( domainEvent.parameters().get() ). append("</td><td>").append( domainEvent.by().get() ). append("</td></tr>"); } } writer.append("</table>\n" + "</body>\n" + "\n" + "</html>" ); } }; representation.setCharacterSet( CharacterSet.UTF_8 ); return representation; } else if (variant.getMediaType().equals( MediaType.APPLICATION_ATOM )) { final Feed feed = new Feed(); feed.setTitle( new Text("Domain events"+ (after == null ? " before "+before : " after "+after))); for (TransactionDomainEvents transactionDomain : transactionDomains) { Entry entry = new Entry(); entry.setPublished( new Date( transactionDomain.timestamp().get()) ); Content content = new Content(); content.setInlineContent( new StringRepresentation( transactionDomain.toJSON(), MediaType.APPLICATION_JSON) ); entry.setContent( content ); feed.getEntries().add( entry ); } WriterRepresentation representation = new WriterRepresentation( MediaType.APPLICATION_ATOM ) { public void write( final Writer writer ) throws IOException { feed.write( writer ); } }; representation.setCharacterSet( CharacterSet.UTF_8 ); return representation; } else { throw new ResourceException( Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE); } } private static class RESTTransactionVisitor implements TransactionVisitor { int maxResults = 100; int currentResults = 0; private List<TransactionDomainEvents> transactionDomains; public RESTTransactionVisitor( List<TransactionDomainEvents> transactionDomains ) { this.transactionDomains = transactionDomains; } public boolean visit( TransactionDomainEvents transactionDomain ) { transactionDomains.add( transactionDomain ); currentResults++; return currentResults < maxResults; } } }