/**
 * @author Daniel Beer ([email protected]), Stephan
 *     Wagner([email protected])
 */
public final class GmplsTopologyHandler {

  /** Singleton Instance. */
  private static GmplsTopologyHandler selfInstance = null;

  private static Logger logger = PhLogger.getLogger(GmplsTopologyHandler.class);

  /**
   * Instance getter.
   *
   * @return Singleton Instance
   */
  public static GmplsTopologyHandler getInstance() {
    if (GmplsTopologyHandler.selfInstance == null) {
      GmplsTopologyHandler.selfInstance = new GmplsTopologyHandler();
    }
    return GmplsTopologyHandler.selfInstance;
  }

  /** Private constructor: Singleton. */
  private GmplsTopologyHandler() {
    // Nothing to do here...
  }

  /**
   * Singleton - Cloning _not_ supported!
   *
   * @return Should never return anything...
   * @throws CloneNotSupportedException Singleton hates to be cloned!
   */
  @Override
  public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
  }

  /*
   * Handler
   * =========================================================================
   */

  /**
   * Retrieve TNA information.
   *
   * @param getEndpointDiscoveryType web service parameter
   * @return GetTNADiscoveryResponseType
   * @throws UnexpectedFaultException in case of error
   */
  @SuppressWarnings("unused")
  public GetEndpointDiscoveryResponseType getEndpointDiscovery(
      final GetEndpointDiscoveryType getEndpointDiscoveryType) throws UnexpectedFaultException {
    final GetEndpointDiscoveryResponseType response = new GetEndpointDiscoveryResponseType();
    try {
      response.getEndpoint().addAll(DbManager.getEndpoints(null));
    } catch (final Exception ex) {
      throw new UnexpectedFaultException(ex);
    }
    return response;
  }

  /**
   * GetPathDiscovery service implementation.
   *
   * @param element the request
   * @return the response
   * @throws UnexpectedFaultException
   */
  @SuppressWarnings("unused")
  public GetPathDiscoveryResponseType getPathDiscovery(final GetPathDiscoveryType element)
      throws UnexpectedFaultException {
    final GetPathDiscoveryResponseType response = new GetPathDiscoveryResponseType();
    for (final Integer i : DbManager.getAllPathIds()) {
      final PathIdentifierType pathId = new PathIdentifierType();
      pathId.setPathIdentifier(i.intValue());
      response.getPathIdentifierList().add(pathId);
    }

    return response;
  }

  /**
   * GetPathStatus Service implementation.
   *
   * @param getPathStatusType the request
   * @return the response
   * @throws PathNotFoundFaultException
   * @throws PathNotFoundFaultException
   */
  public GetPathStatusResponseType getPathStatus(final GetPathStatusType getPathStatusType)
      throws PathNotFoundFaultException {
    final GetPathStatusResponseType response = new GetPathStatusResponseType();
    final PathType path = new PathType();
    LspInformation lspInformation;
    try {
      lspInformation =
          DbManager.getPathInformation(getPathStatusType.getPathIdentifier().getPathIdentifier());
      if (!checkPathStatus(lspInformation)) {
        logger.debug("Path does not exist anymore");
        throw new PathNotFoundFaultException("Path does not exist anymore");
      }
      path.setSourceTNA(lspInformation.getSourceDevice().getTnaAddress());
      path.setDestinationTNA(lspInformation.getDestinationDevice().getTnaAddress());
      path.setBandwidth(lspInformation.getBandwidth());
    } catch (final Exception e) {
      throw new PathNotFoundFaultException(e);
    }
    response.setPath(path);
    return response;
  }

  public boolean checkPathStatus(LspInformation lspInformation)
      throws UnexpectedFaultException, PathNotFoundFaultException {
    final ConfigurationManager configManager =
        new ConfigurationManager(lspInformation.getSourceDevice().getModule());
    if (!configManager.getStatus(lspInformation)) {
      DbManager.insertLog(
          "Cleaned lsp with pathId "
              + lspInformation.getPathId()
              + " and description: "
              + lspInformation.getLspDescriptor());
      logger.debug(
          "Cleaned lsp with pathId "
              + lspInformation.getPathId()
              + " and description: "
              + lspInformation.getLspDescriptor());
      DbManager.deletePath(lspInformation.getPathId());
      try {
        configManager.terminatePath(lspInformation);
      } catch (final Exception ex) {
        DbManager.insertLog("Could not be deleted on router-> might be already deleted.");
        logger.debug("Could not be deleted on router-> might be already deleted.");

        logger.error(ex.getMessage(), ex);
      }
      return false;
    }
    return true;
  }
}
/**
 * @author Stephan Wagner ([email protected]), Daniel Beer
 *     ([email protected])
 */
public final class CreationHandler {

  /** Singleton instance. */
  private static CreationHandler selfInstance = null;

  private static Logger logger = PhLogger.getLogger(CreationHandler.class);

  /**
   * Instance getter.
   *
   * @return Singleton Instance
   */
  public static CreationHandler getInstance() {
    if (selfInstance == null) {
      selfInstance = new CreationHandler();
    }
    return selfInstance;
  }

  /**
   * sets up a gmpls connection through the gmpls web service.
   *
   * @param gmplsConnection connection to be established
   * @return true if connection could be established
   * @throws InvalidRequestFaultException request was not valid
   * @throws SoapFault should not happen
   */
  public static int setUpConnection(final GmplsConnection gmplsConnection) throws SoapFault {
    AJaxbSerializer jserGmpls =
        org.opennaas.extensions.gmpls.serviceinterface.databinding.utils.JaxbSerializer
            .getInstance();
    try {
      gmplsConnection.setStatus(StatusType.SETUP_IN_PROGRESS);
      DbManager.updateStatus(gmplsConnection, "Trying to setup the Connection");
    } catch (UnexpectedFaultException e1) {
      e1.printStackTrace();
    }
    final CreatePathResponse response =
        (CreatePathResponse)
            jserGmpls.elementToObject(
                ContextListener.getGmplsWS()
                    .createPath(jserGmpls.objectToElement(gmplsConnection.getCreatePathRequest())));
    CreatePathResponseType resp = response.getCreatePathResponse();
    gmplsConnection.setPathId(resp.getPathIdentifier().getPathIdentifier());
    gmplsConnection.setStatus(StatusType.ACTIVE);

    DbManager.updatePathId(gmplsConnection);
    DbManager.updateStatus(gmplsConnection, "PathId is " + gmplsConnection.getPathId());
    Notifications.subscribe(gmplsConnection.getPathId());
    return gmplsConnection.getPathId();
  }

  /** Private constructor: Singleton. */
  private CreationHandler() {
    //
  }

  /**
   * Singleton - Cloning _not_ supported!
   *
   * @return Should never return anything...
   * @throws CloneNotSupportedException Singleton hates to be cloned!
   */
  @Override
  public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
  }

  /**
   * Creates a new reservation in the thin Nrps.
   *
   * @param createReservationRequest request
   * @return response for request as CreateReservationResponseType
   * @throws UnexpectedFaultException if reservation is not of type fixed
   * @throws InvalidReservationIDFaultException
   */
  public CreateReservationResponseType createReservation(
      final CreateReservationType createReservationRequest)
      throws UnexpectedFaultException, InvalidReservationIDFaultException {

    CreateReservationResponseType response = new CreateReservationResponseType();

    long jobId = System.currentTimeMillis();
    if (createReservationRequest.isSetJobID()
        && createReservationRequest.getJobID().longValue() > 0) {
      jobId = createReservationRequest.getJobID().longValue();
    }

    long reservationId =
        DbManager.insertReservation(jobId, createReservationRequest.getNotificationConsumerURL());

    boolean success = true;
    boolean partSuccess = false;

    List<GmplsConnection> connections = new ArrayList<GmplsConnection>();

    response.setJobID(Long.valueOf(jobId));
    response.setReservationID(WebserviceUtils.convertReservationID(reservationId));

    for (ServiceConstraintType sct : createReservationRequest.getService()) {
      if (sct.getTypeOfReservation()
          .equals(
              org.opennaas.extensions.idb.serviceinterface.databinding.jaxb.ReservationType
                  .FIXED)) {

        Calendar calStart =
            Helpers.xmlCalendarToCalendar(sct.getFixedReservationConstraints().getStartTime());
        Timestamp startTime = new Timestamp(calStart.getTime().getTime());

        calStart.setTimeZone(SimpleTimeZone.getDefault());
        calStart.add(Calendar.SECOND, sct.getFixedReservationConstraints().getDuration());
        Timestamp endTime = new Timestamp(calStart.getTimeInMillis());
        for (ConnectionConstraintType cct : sct.getConnections()) {
          GmplsConnection con = new GmplsConnection();
          con.setJobId(jobId);
          con.setReservationId(reservationId);
          con.setServiceId(sct.getServiceID());
          con.setConnectionId(cct.getConnectionID());
          con.setSrcTNA(cct.getSource().getEndpointId());
          con.setDestTNA(cct.getTarget().get(0).getEndpointId());
          con.setStartTime(startTime);
          con.setEndTime(endTime);
          con.setBandwidth(cct.getMinBW());
          con.setAutoActivation(sct.isAutomaticActivation());

          try {
            partSuccess = DbManager.insertConnection(con);
          } catch (SourcePortUnavailableException e) {
            partSuccess = false;
            logger.error(e.getMessage(), e);
          } catch (DestinationPortUnavailableException e) {
            partSuccess = false;
            logger.error(e.getMessage(), e);
          } catch (SourceAndDestinationPortUnavailableException e) {
            partSuccess = false;
            logger.error(e.getMessage(), e);
          } catch (PathNotFoundException e) {
            partSuccess = false;
            logger.error(e.getMessage(), e);
          }

          if (partSuccess) {
            connections.add(con);
          }

          success &= partSuccess;
        }
      } else {
        DbManager.deleteWholeReservation(reservationId);
        throw new UnexpectedFaultException("Only FIXED ReservationType supported");
      }
    }

    if (!success) {
      logger.debug("No success");
      DbManager.deleteWholeReservation(reservationId);
      throw new UnexpectedFaultException("No Path found.");
    }
    for (GmplsConnection gmplsConnection : connections) {
      try {
        if (gmplsConnection.isAutoActivation()) {

          if (gmplsConnection
                  .getStartTime()
                  .before(Helpers.xmlCalendarToDate(Helpers.generateXMLCalendar(0, 0)))
              && gmplsConnection
                  .getEndTime()
                  .after(Helpers.xmlCalendarToDate(Helpers.generateXMLCalendar()))) {
            if (0 <= setUpConnection(gmplsConnection)) {
              JobManager.getInstance().schedulePathTermination(gmplsConnection);

            } else {
              gmplsConnection.setStatus(StatusType.UNKNOWN);
              DbManager.updateStatus(
                  gmplsConnection, "Path could not be set up! PathId returned is 0");
              throw new UnexpectedFaultException("Path could not be set up");
            }
          } else {
            JobManager.getInstance().schedulePathSetUp(gmplsConnection);
            JobManager.getInstance().schedulePathTermination(gmplsConnection);
            gmplsConnection.setStatus(StatusType.PENDING);
            DbManager.updateStatus(gmplsConnection, "Connection has been scheduled");
          }
        }
      } catch (SchedulerException e) {
        gmplsConnection.setStatus(StatusType.UNKNOWN);
        DbManager.updateStatus(gmplsConnection, e.getMessage());
        throw new UnexpectedFaultException(e);
      } catch (InvalidRequestFaultException e) {
        gmplsConnection.setStatus(StatusType.UNKNOWN);
        DbManager.updateStatus(gmplsConnection, e.getMessage());
        throw new UnexpectedFaultException(e);
      } catch (SoapFault e) {
        gmplsConnection.setStatus(StatusType.UNKNOWN);
        DbManager.updateStatus(gmplsConnection, e.getMessage());
        throw new UnexpectedFaultException(e);
      }
    }
    Notifications.addTopic(response.getReservationID());
    return response;
  }
}