private void preProcessTimeRef(final Collection<TypedCircularMessage> typedCircularMessages) {
   ticksPerNano = -1;
   long timeClock1 = -1;
   long timeClock2 = -1;
   long timeTicks1 = -1;
   long timeTicks2 = -1;
   long timeClocksPerSec = -1;
   for (final TypedCircularMessage msg : typedCircularMessages) {
     if (msg.getStruct().getId() != Message.TIME_REF.srlTypeId()) {
       continue;
     }
     final Long secondsSince1970 = (Long) msg.getValue("secondsSince1970");
     if (secondsSince1970 != null) {
       // TODO: save timebase in header?
     }
     final Long clock = (Long) msg.getValue("clock");
     if (clock == null) {
       continue;
     }
     final Long clocksPerSec = (Long) msg.getValue("clocksPerSec");
     if (clocksPerSec == null || clocksPerSec < 1) {
       continue;
     }
     if (timeClock1 == -1) {
       timeClock1 = clock;
       timeTicks1 = ((CircularMessage) msg.getMessage()).getTs();
       timeClock2 = -1;
       continue;
     }
     if (timeClock2 == -1) {
       timeClock2 = clock;
       timeTicks2 = ((CircularMessage) msg.getMessage()).getTs();
       timeClocksPerSec = clocksPerSec;
       break;
     }
   }
   if (timeClock1 == -1 || timeClock2 == -1) {
     return;
   }
   if (timeTicks1 == -1 || timeTicks2 == -1) {
     return;
   }
   if (timeClock1 > timeClock2) {
     long temp = timeClock2;
     timeClock2 = timeClock1;
     timeClock1 = temp;
     temp = timeTicks2;
     timeTicks2 = timeTicks1;
     timeTicks1 = temp;
   }
   if (timeClock1 >= timeClock2 || timeTicks1 >= timeTicks2) {
     return;
   }
   final double temp1 = timeClocksPerSec * (timeTicks2 - timeTicks1);
   final double temp2 = NANO_PER_SEC * (timeClock2 - timeClock1);
   ticksPerNano = temp1 / temp2;
 }
  private Object getValue(final TypedCircularMessage message, final String name) {
    final Object value = message.getValue(name);
    if (value == null) {
      Logger.err("WARNING: No such value: " + name);
      return null;
    }
    if (value instanceof IPointer) {
      final IPointer p = (IPointer) value;

      if (p.getValue() == null) {
        if (!name.equals(SRLEventReader.FN_RECEIVER_ACTOR_INSTANCE)
            && !name.equals(SRLEventReader.FN_SENDER_ACTOR_INSTANCE)) {
          Logger.err(
              "Note: value of '"
                  + name
                  + "' on '"
                  + message.getStruct().getName()
                  + "' is an unresolved pointer value (NULL). Will use pointer ("
                  + p.getPointer()
                  + ")");
        }
        if (name.equals(SRLEventReader.FN_STATE) && p.getPointer() == 0L) {
          return null;
        }
        return p.getPointer();
      }
      return p.getValue();
    }

    if (value.getClass().isArray()) {
      final Object[] arr = (Object[]) value;
      return Arrays.asList(arr);
    }
    return value;
  }
 private String getFunctionName(final TypedCircularMessage message) {
   Object functionPointer = message.getValue(FUNCTION_FIELD);
   TypedLinearMessage functionMessage = functionMap.get(functionPointer);
   String functionName = null;
   if (functionMessage == null) {
     if (functionPointer instanceof Pointer) {
       Pointer ptr = (Pointer) functionPointer;
       functionName = Long.toHexString(ptr.getPointer());
     } else {
       throw new IllegalStateException("function field is not a pointer!");
     }
   } else {
     functionName = (String) functionMessage.getValue(FN_NAME);
   }
   return functionName;
 }
 UmlSend(final TypedCircularMessage message) {
   senderClassId = (Long) message.getValue("senderClassId");
   senderInstanceId = (Long) message.getValue("senderInstanceId");
   receiverClassId = (Long) message.getValue(RECEIVER_CLASS_ID);
   receiverInstanceId = (Long) message.getValue(RECEIVER_INSTANCE_ID);
   signalId = (Long) message.getValue(SIGNAL_ID);
   Object value = message.getValue(SIGNAL_INSTANCE_ID);
   if (value == null) {
     signalInstanceId = 0;
   } else {
     signalInstanceId = (Long) value;
   }
 }
 UmlReceive(final TypedCircularMessage message) {
   receiverClassId = (Long) message.getValue(RECEIVER_CLASS_ID);
   receiverInstanceId = (Long) message.getValue(RECEIVER_INSTANCE_ID);
   signalId = (Long) message.getValue(SIGNAL_ID);
   nextStateId = (Long) message.getValue("nextStateId");
   finishHi = (Long) message.getValue(FINISH_HI);
   finishLo = (Long) message.getValue(FINISH_LO);
   Object value = message.getValue(SIGNAL_INSTANCE_ID);
   if (value == null) {
     signalInstanceId = 0;
   } else {
     signalInstanceId = (Long) value;
   }
 }
  private void getUserEvent(TypedCircularMessage message, long ts) {
    Struct struct = message.getStruct();
    userStructs.add(struct);

    int structId = struct.getId();
    FieldValues values = new FieldValues();
    List<Field> fields = struct.getFields();
    for (Field field : fields) {
      String fieldName = field.getName();
      Object value = message.getValue(fieldName);
      Type type = field.getType();
      if (field.isNullTerminated()) {
        if (type.getId() == Type.Srl.t_char.getId()) {
          String s = (String) value;
          values.addStringValue(s);
        } else {
          throw new UnsupportedOperationException(
              "Only null terminated 'char' sequences are currently supported, type is " + type);
        }
      } else if (field.getNumElements() == 1) {
        Srl srlType = Srl.valueOf(type.getId());
        switch (srlType) {
          case t_srl_I32:
          case t_srl_U32:
            Long i = (Long) value;
            values.addLongValue(i);
            break;
          default:
            throw new UnsupportedOperationException("Unsupported type: " + type);
        }

      } else {
        throw new UnsupportedOperationException(
            "Arrays are currently not supported, type is " + type);
      }
    }
    client.eventRead(new GenericEventInfo(ts, structId, values));
  }