# TimelineForScheduleConcern.java

    /*
     * Copyright (c) 2012, Niclas Hedhman.
     *
     * Licensed  under the  Apache License,  Version 2.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.apache.org/licenses/LICENSE-2.0
     *
     * 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 org.qi4j.library.scheduler.timeline;

    import java.io.BufferedOutputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.PrintStream;
    import java.util.List;
    import org.qi4j.api.concern.ConcernOf;
    import org.qi4j.api.injection.scope.Structure;
    import org.qi4j.api.injection.scope.This;
    import org.qi4j.api.structure.Module;
    import org.qi4j.api.value.ValueBuilder;
    import org.qi4j.library.scheduler.schedule.Schedule;

    public abstract class TimelineForScheduleConcern
        extends ConcernOf<Schedule>
        implements Schedule
    {
        @This
        private TimelineScheduleState state;

        @Structure
        private Module module;

        @Override
        public void taskStarting()
        {
            addRecord( TimelineRecordStep.STARTED, "" );
            next.taskStarting();
        }

        @Override
        public void taskCompletedSuccessfully()
        {
            addRecord( TimelineRecordStep.SUCCESS, "" );
            next.taskCompletedSuccessfully();
        }

        @Override
        public void taskCompletedWithException( RuntimeException ex )
        {
            TimelineRecordStep step = TimelineRecordStep.FAILURE;
            String details = "Exception occurred:" + getStackTrace( ex );
            addRecord( step, details );
            next.taskCompletedWithException( ex );
        }

        private void addRecord( TimelineRecordStep step, String details )
        {
            ValueBuilder<TimelineRecord> builder = module.newValueBuilder( TimelineRecord.class );
            TimelineRecord prototype = builder.prototype();
            prototype.step().set( step );
            prototype.taskName().set( task().get().name().get() );
            List<String> tags = task().get().tags().get();
            prototype.taskTags().set( tags );
            prototype.timestamp().set( System.currentTimeMillis() );
            prototype.scheduleIdentity().set( this.identity().get() );
            prototype.details().set( details );
            TimelineRecord record = builder.newInstance();
            List<TimelineRecord> timelineRecords = state.history().get();
            timelineRecords.add( record );
            state.history().set( timelineRecords );
        }

        private String getStackTrace( RuntimeException ex )
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream( 1000 );
            BufferedOutputStream out = new BufferedOutputStream( baos );
            PrintStream print = new PrintStream( out );
            ex.printStackTrace( print );
            print.flush();
            return baos.toString();
        }
    }