code: // Licensed to the Software Freedom Conservancy (SFC) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The SFC licenses this file
  // to you 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.openqa.selenium.grid.graphql;
  
  import java.net.URI;
  import java.time.Duration;
  import java.time.Instant;
  import java.time.ZoneId;
  import java.time.format.DateTimeFormatter;
  import org.openqa.selenium.Capabilities;
  import org.openqa.selenium.grid.data.Slot;
  import org.openqa.selenium.internal.Require;
  import org.openqa.selenium.json.Json;
  
  public class Session {
  
    private static final DateTimeFormatter DATE_TIME_FORMATTER =
        DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").withZone(ZoneId.systemDefault());
  
    private final String id;
    private final Capabilities capabilities;
    private final Instant startTime;
    private final URI uri;
    private final String nodeId;
    private final URI nodeUri;
    private final Slot slot;
    private static final Json JSON = new Json();
  
    public Session(
        String id,
        Capabilities capabilities,
        Instant startTime,
        URI uri,
        String nodeId,
        URI nodeUri,
        Slot slot) {
      this.id = Require.nonNull("Session id", id);
      this.capabilities = Require.nonNull("Session capabilities", capabilities);
      this.startTime = Require.nonNull("Session Start time", startTime);
      this.uri = Require.nonNull("Session uri", uri);
      this.nodeId = Require.nonNull("Node id", nodeId);
      this.nodeUri = Require.nonNull("Node uri", nodeUri);
      this.slot = Require.nonNull("Slot", slot);
    }
  
    public String getId() {
      return id;
    }
  
    public String getCapabilities() {
      return JSON.toJson(capabilities);
    }
  
    public String getStartTime() {
      return DATE_TIME_FORMATTER.format(startTime);
    }
  
    public URI getUri() {
      return uri;
    }
  
    public String getNodeId() {
      return nodeId;
    }
  
    public URI getNodeUri() {
      return nodeUri;
    }
  
    public String getSessionDurationMillis() {
      long duration = Duration.between(startTime, Instant.now()).toMillis();
      return String.valueOf(duration);
    }
  
    public org.openqa.selenium.grid.graphql.Slot getSlot() {
      return new org.openqa.selenium.grid.graphql.Slot(
          slot.getId().getSlotId(), slot.getStereotype(), slot.getLastStarted());
    }
  }
  