package io.micronaut.health;

import io.micronaut.context.event.ApplicationEventListener;
import io.micronaut.context.event.ApplicationEventPublisher;
import io.micronaut.discovery.ServiceInstance;
import io.micronaut.discovery.event.ServiceReadyEvent;
import io.micronaut.scheduling.annotation.Scheduled;
import jakarta.inject.Singleton;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A scheduled task that sends a periodic heartbeat whilst the server is active.
 *
 * @author graemerocher
 * @since 1.0
 */
@Singleton
@HeartbeatEnabled
public class HeartbeatTask implements ApplicationEventListener<ServiceReadyEvent> {

    private final Set<ServiceInstance> eventsReference = ConcurrentHashMap.newKeySet();

    private final ApplicationEventPublisher eventPublisher;

    private final CurrentHealthStatus currentHealthStatus;

    /**
     * @param eventPublisher      To publish the events related to heartbeat
     * @param configuration       The configurations for heartbeat
     * @param currentHealthStatus The current status of health indicator
     */
    public HeartbeatTask(ApplicationEventPublisher eventPublisher, HeartbeatConfiguration configuration, CurrentHealthStatus currentHealthStatus) {
        this.eventPublisher = eventPublisher;
        this.currentHealthStatus = currentHealthStatus;
    }

    /**
     * Publish the heartbeat event with current health status.
     */
    @Scheduled(fixedDelay = "${micronaut.heartbeat.interval:15s}", initialDelay = "${micronaut.heartbeat.initial-delay:5s}")
    public void pulsate() {
        for (ServiceInstance instance : eventsReference) {
            eventPublisher.publishEvent(new HeartbeatEvent(instance, currentHealthStatus.current()));
        }
    }

    @Override
    public void onApplicationEvent(ServiceReadyEvent event) {
        eventsReference.add(event.ge


@Scheduled(fixedDelay = "${micronaut.heartbeat.interval:15s}", initialDelay = "${micronaut.heartbeat.initial-delay:5s}")
    public void pulsate() {
        for (ServiceInstance instance : eventsReference) {
            eventPublisher.publishEvent(new HeartbeatEvent(instance, currentHealthStatus.current()));
        }
    }

package io.micronaut.health;

import io.micronaut.context.event.ApplicationEventListener;
import io.micronaut.context.event.ApplicationEventPublisher;
import io.micronaut.discovery.ServiceInstance;
import io.micronaut.discovery.event.ServiceReadyEvent;
import io.micronaut.scheduling.annotation.Scheduled;
import jakarta.inject.Singleton;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A scheduled task that sends a periodic heartbeat whilst the server is active.
 *
 * @author graemerocher
 * @since 1.0
 */
@Singleton
@HeartbeatEnabled
public class HeartbeatTask implements ApplicationEventListener<ServiceReadyEvent> {

    private final Set<ServiceInstance> eventsReference = ConcurrentHashMap.newKeySet();

    private final ApplicationEventPublisher eventPublisher;

    private final CurrentHealthStatus currentHealthStatus;

    /**
     * @param eventPublisher      To publish the events related to heartbeat
     * @param configuration       The configurations for heartbeat
     * @param currentHealthStatus The current status of health indicator
     */
    public HeartbeatTask(ApplicationEventPublisher eventPublisher, HeartbeatConfiguration configuration, CurrentHealthStatus currentHealthStatus) {
        this.eventPublisher = eventPublisher;
        this.currentHealthStatus = currentHealthStatus;
    }

    /**
     * Publish the heartbeat event with current health status.
     */

    @Override
    public void onApplicationEvent(ServiceReadyEvent event) {
        eventsReference.add(event.getSource());
    }
}


package com.android.internal.telephony.uicc;

import android.telephony.Rlog;
import com.android.internal.telephony.uicc.IccCardStatus.PinState;

public class IccCardApplicationStatus {

    public String aid;

    public String app_label;

    public AppState app_state;

    public AppType app_type;

    public PersoSubState perso_substate;

    public PinState pin1;

    public int pin1_replaced;

    public PinState pin2;

    public enum AppState {

        APPSTATE_UNKNOWN,
        APPSTATE_DETECTED,
        APPSTATE_PIN,
        APPSTATE_PUK,
        APPSTATE_SUBSCRIPTION_PERSO,
        APPSTATE_READY;

        boolean isPinRequired() {
            return this == APPSTATE_PIN;
        }

        boolean isPukRequired() {
            return this == APPSTATE_PUK;
        }

        boolean isSubscriptionPersoEnabled() {
            return this == APPSTATE_SUBSCRIPTION_PERSO;
        }

        boolean isAppReady() {
            return this == APPSTATE_READY;
        }

        boolean isAppNotReady() {
            if (this == APPSTATE_UNKNOWN || this == APPSTATE_DETECTED) {
                return true;
            }
            return false;
        }
    }

    public enum AppType {

        APPTYPE_UNKNOWN,
        APPTYPE_SIM,
        APPTYPE_USIM,
        APPTYPE_RUIM,
        APPTYPE_CSIM,
        APPTYPE_ISIM
    }

    public enum PersoSubState {

        PERSOSUBSTATE_UNKNOWN,
        PERSOSUBSTATE_IN_PROGRESS,
        PERSOSUBSTATE_READY,
        PERSOSUBSTATE_SIM_NETWORK,
        PERSOSUBSTATE_SIM_NETWORK_SUBSET,
        PERSOSUBSTATE_SIM_CORPORATE,
        PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
        PERSOSUBSTATE_SIM_SIM,
        PERSOSUBSTATE_SIM_NETWORK_PUK,
        PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
        PERSOSUBSTATE_SIM_CORPORATE_PUK,
        PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
        PERSOSUBSTATE_SIM_SIM_PUK,
        PERSOSUBSTATE_RUIM_NETWORK1,
        PERSOSUBSTATE_RUIM_NETWORK2,
        PERSOSUBSTATE_RUIM_HRPD,
        PERSOSUBSTATE_RUIM_CORPORATE,
        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
        PERSOSUBSTATE_RUIM_RUIM,
        PERSOSUBSTATE_RUIM_NETWORK1_PUK,
        PERSOSUBSTATE_RUIM_NETWORK2_PUK,
        PERSOSUBSTATE_RUIM_HRPD_PUK,
        PERSOSUBSTATE_RUIM_CORPORATE_PUK,
        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
        PERSOSUBSTATE_RUIM_RUIM_PUK;

        boolean isPersoSubStateUnknown() {
            return this == PERSOSUBSTATE_UNKNOWN;
        }
    }

    public AppType AppTypeFromRILInt(int type) {
        switch(type) {
            case 0:
                return AppType.APPTYPE_UNKNOWN;
            case 1:
                return AppType.APPTYPE_SIM;
            case 2:
                return AppType.APPTYPE_USIM;
            case 3:
                return AppType.APPTYPE_RUIM;
            case 4:
                return AppType.APPTYPE_CSIM;
            case 5:
                return AppType.APPTYPE_ISIM;
            default:
                AppType newType = AppType.APPTYPE_UNKNOWN;
                loge("AppTypeFromRILInt: bad RIL_AppType: " + type + " use APPTYPE_UNKNOWN");
                return newType;
        }
    }

    public AppState AppStateFromRILInt(int state) {
        switch(state) {
            case 0:
                return AppState.APPSTATE_UNKNOWN;
            case 1:
                return AppState.APPSTATE_DETECTED;
            case 2:
                return AppState.APPSTATE_PIN;
            case 3:
                return AppState.APPSTATE_PUK;
            case 4:
                return AppState.APPSTATE_SUBSCRIPTION_PERSO;
            case 5:
                return AppState.APPSTATE_READY;
            default:
                AppState newState = AppState.APPSTATE_UNKNOWN;
                loge("AppStateFromRILInt: bad state: " + state + " use APPSTATE_UNKNOWN");
                return newState;
        }
    }

    public PersoSubState PersoSubstateFromRILInt(int substate) {
        switch(substate) {
            case 0:
                return PersoSubState.PERSOSUBSTATE_UNKNOWN;
            case 1:
                return PersoSubState.PERSOSUBSTATE_IN_PROGRESS;
            case 2:
                return PersoSubState.PERSOSUBSTATE_READY;
            case 3:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK;
            case 4:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET;
            case 5:
                return PersoSubState.PERSOSUBSTATE_SIM_CORPORATE;
            case 6:
                return PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER;
            case 7:
                return PersoSubState.PERSOSUBSTATE_SIM_SIM;
            case 8:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_PUK;
            case 9:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK;
            case 10:
                return PersoSubState.PERSOSUBSTATE_SIM_CORPORATE_PUK;
            case 11:
                return PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK;
            case 12:
                return PersoSubState.PERSOSUBSTATE_SIM_SIM_PUK;
            case 13:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1;
            case 14:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2;
            case 15:
                return PersoSubState.PERSOSUBSTATE_RUIM_HRPD;
            case 16:
                return PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE;
            case 17:
                return PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER;
            case 18:
                return PersoSubState.PERSOSUBSTATE_RUIM_RUIM;
            case 19:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1_PUK;
            case 20:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2_PUK;
            case 21:
                return PersoSubState.PERSOSUBSTATE_RUIM_HRPD_PUK;
            case 22:
                return PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE_PUK;
            case 23:
                return PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK;
            case 24:
                return PersoSubState.PERSOSUBSTATE_RUIM_RUIM_PUK;
            default:
                PersoSubState newSubState = PersoSubState.PERSOSUBSTATE_UNKNOWN;
                loge("PersoSubstateFromRILInt: bad substate: " + substate + " use PERSOSUBSTATE_UNKNOWN");
                return newSubState;
        }
    }

    public PinState PinStateFromRILInt(int state) {
        switch(state) {
            case 0:
                return PinState.PINSTATE_UNKNOWN;
            case 1:
                return PinState.PINSTATE_ENABLED_NOT_VERIFIED;
            case 2:
                return PinState.PINSTATE_ENABLED_VERIFIED;
            case 3:
                return PinState.PINSTATE_DISABLED;
            case 4:
                return PinState.PINSTATE_ENABLED_BLOCKED;
            case 5:
                return PinState.PINSTATE_ENABLED_PERM_BLOCKED;
            default:
                PinState newPinState = PinState.PINSTATE_UNKNOWN;
                loge("PinStateFromRILInt: bad pin state: " + state + " use PINSTATE_UNKNOWN");
                return newPinState;
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{").append(this.app_type).append(",").append(this.app_state);
        if (this.app_state == AppState.APPSTATE_SUBSCRIPTION_PERSO) {
            sb.append(",").append(this.perso_substate);
        }
        if (!(this.app_type == AppType.APPTYPE_CSIM || this.app_type == AppType.APPTYPE_USIM)) {
            if (this.app_type == AppType.APPTYPE_ISIM) {
            }
            sb.append("}");
            return sb.toString();
        }
        sb.append(",pin1=").append(this.pin1);
        sb.append(",pin2=").append(this.pin2);
        sb.append("}");
        return sb.toString();
    }

{
        Rlog.e("IccCardApplicationStatus", s);
    }
}


{
            return this == APPSTATE_SUBSCRIPTION_PERSO;
        }

package com.android.internal.telephony.uicc;

import android.telephony.Rlog;
import com.android.internal.telephony.uicc.IccCardStatus.PinState;

public class IccCardApplicationStatus {

    public String aid;

    public String app_label;

    public AppState app_state;

    public AppType app_type;

    public PersoSubState perso_substate;

    public PinState pin1;

    public int pin1_replaced;

    public PinState pin2;

    public enum AppState {

        APPSTATE_UNKNOWN,
        APPSTATE_DETECTED,
        APPSTATE_PIN,
        APPSTATE_PUK,
        APPSTATE_SUBSCRIPTION_PERSO,
        APPSTATE_READY;

        boolean isPinRequired() {
            return this == APPSTATE_PIN;
        }

        boolean isPukRequired() {
            return this == APPSTATE_PUK;
        }

        boolean isSubscriptionPersoEnabled()

        boolean isAppReady() {
            return this == APPSTATE_READY;
        }

        boolean isAppNotReady() {
            if (this == APPSTATE_UNKNOWN || this == APPSTATE_DETECTED) {
                return true;
            }
            return false;
        }
    }

    public enum AppType {

        APPTYPE_UNKNOWN,
        APPTYPE_SIM,
        APPTYPE_USIM,
        APPTYPE_RUIM,
        APPTYPE_CSIM,
        APPTYPE_ISIM
    }

    public enum PersoSubState {

        PERSOSUBSTATE_UNKNOWN,
        PERSOSUBSTATE_IN_PROGRESS,
        PERSOSUBSTATE_READY,
        PERSOSUBSTATE_SIM_NETWORK,
        PERSOSUBSTATE_SIM_NETWORK_SUBSET,
        PERSOSUBSTATE_SIM_CORPORATE,
        PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
        PERSOSUBSTATE_SIM_SIM,
        PERSOSUBSTATE_SIM_NETWORK_PUK,
        PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
        PERSOSUBSTATE_SIM_CORPORATE_PUK,
        PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
        PERSOSUBSTATE_SIM_SIM_PUK,
        PERSOSUBSTATE_RUIM_NETWORK1,
        PERSOSUBSTATE_RUIM_NETWORK2,
        PERSOSUBSTATE_RUIM_HRPD,
        PERSOSUBSTATE_RUIM_CORPORATE,
        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
        PERSOSUBSTATE_RUIM_RUIM,
        PERSOSUBSTATE_RUIM_NETWORK1_PUK,
        PERSOSUBSTATE_RUIM_NETWORK2_PUK,
        PERSOSUBSTATE_RUIM_HRPD_PUK,
        PERSOSUBSTATE_RUIM_CORPORATE_PUK,
        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
        PERSOSUBSTATE_RUIM_RUIM_PUK;

        boolean isPersoSubStateUnknown() {
            return this == PERSOSUBSTATE_UNKNOWN;
        }
    }

    public AppType AppTypeFromRILInt(int type) {
        switch(type) {
            case 0:
                return AppType.APPTYPE_UNKNOWN;
            case 1:
                return AppType.APPTYPE_SIM;
            case 2:
                return AppType.APPTYPE_USIM;
            case 3:
                return AppType.APPTYPE_RUIM;
            case 4:
                return AppType.APPTYPE_CSIM;
            case 5:
                return AppType.APPTYPE_ISIM;
            default:
                AppType newType = AppType.APPTYPE_UNKNOWN;
                loge("AppTypeFromRILInt: bad RIL_AppType: " + type + " use APPTYPE_UNKNOWN");
                return newType;
        }
    }

    public AppState AppStateFromRILInt(int state) {
        switch(state) {
            case 0:
                return AppState.APPSTATE_UNKNOWN;
            case 1:
                return AppState.APPSTATE_DETECTED;
            case 2:
                return AppState.APPSTATE_PIN;
            case 3:
                return AppState.APPSTATE_PUK;
            case 4:
                return AppState.APPSTATE_SUBSCRIPTION_PERSO;
            case 5:
                return AppState.APPSTATE_READY;
            default:
                AppState newState = AppState.APPSTATE_UNKNOWN;
                loge("AppStateFromRILInt: bad state: " + state + " use APPSTATE_UNKNOWN");
                return newState;
        }
    }

    public PersoSubState PersoSubstateFromRILInt(int substate) {
        switch(substate) {
            case 0:
                return PersoSubState.PERSOSUBSTATE_UNKNOWN;
            case 1:
                return PersoSubState.PERSOSUBSTATE_IN_PROGRESS;
            case 2:
                return PersoSubState.PERSOSUBSTATE_READY;
            case 3:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK;
            case 4:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET;
            case 5:
                return PersoSubState.PERSOSUBSTATE_SIM_CORPORATE;
            case 6:
                return PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER;
            case 7:
                return PersoSubState.PERSOSUBSTATE_SIM_SIM;
            case 8:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_PUK;
            case 9:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK;
            case 10:
                return PersoSubState.PERSOSUBSTATE_SIM_CORPORATE_PUK;
            case 11:
                return PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK;
            case 12:
                return PersoSubState.PERSOSUBSTATE_SIM_SIM_PUK;
            case 13:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1;
            case 14:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2;
            case 15:
                return PersoSubState.PERSOSUBSTATE_RUIM_HRPD;
            case 16:
                return PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE;
            case 17:
                return PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER;
            case 18:
                return PersoSubState.PERSOSUBSTATE_RUIM_RUIM;
            case 19:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1_PUK;
            case 20:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2_PUK;
            case 21:
                return PersoSubState.PERSOSUBSTATE_RUIM_HRPD_PUK;
            case 22:
                return PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE_PUK;
            case 23:
                return PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK;
            case 24:
                return PersoSubState.PERSOSUBSTATE_RUIM_RUIM_PUK;
            default:
                PersoSubState newSubState = PersoSubState.PERSOSUBSTATE_UNKNOWN;
                loge("PersoSubstateFromRILInt: bad substate: " + substate + " use PERSOSUBSTATE_UNKNOWN");
                return newSubState;
        }
    }

    public PinState PinStateFromRILInt(int state) {
        switch(state) {
            case 0:
                return PinState.PINSTATE_UNKNOWN;
            case 1:
                return PinState.PINSTATE_ENABLED_NOT_VERIFIED;
            case 2:
                return PinState.PINSTATE_ENABLED_VERIFIED;
            case 3:
                return PinState.PINSTATE_DISABLED;
            case 4:
                return PinState.PINSTATE_ENABLED_BLOCKED;
            case 5:
                return PinState.PINSTATE_ENABLED_PERM_BLOCKED;
            default:
                PinState newPinState = PinState.PINSTATE_UNKNOWN;
                loge("PinStateFromRILInt: bad pin state: " + state + " use PINSTATE_UNKNOWN");
                return newPinState;
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{").append(this.app_type).append(",").append(this.app_state);
        if (this.app_state == AppState.APPSTATE_SUBSCRIPTION_PERSO) {
            sb.append(",").append(this.perso_substate);
        }
        if (!(this.app_type == AppType.APPTYPE_CSIM || this.app_type == AppType.APPTYPE_USIM)) {
            if (this.app_type == AppType.APPTYPE_ISIM) {
            }
            sb.append("}");
            return sb.toString();
        }
        sb.append(",pin1=").append(this.pin1);
        sb.append(",pin2=").append(this.pin2);
        sb.append("}");
        return sb.toString();
    }

    private void loge(String s) {
        Rlog.e("IccCardApplicationStatus", s);
    }
}


package com.android.internal.telephony.uicc;

import android.telephony.Rlog;
import com.android.internal.telephony.uicc.IccCardStatus.PinState;

public class IccCardApplicationStatus {

    public String aid;

    public String app_label;

    public AppState app_state;

    public AppType app_type;

    public PersoSubState perso_substate;

    public PinState pin1;

    public int pin1_replaced;

    public PinState pin2;

    public enum AppState {

        APPSTATE_UNKNOWN,
        APPSTATE_DETECTED,
        APPSTATE_PIN,
        APPSTATE_PUK,
        APPSTATE_SUBSCRIPTION_PERSO,
        APPSTATE_READY;

        boolean isPinRequired() {
            return this == APPSTATE_PIN;
        }

        boolean isPukRequired() {
            return this == APPSTATE_PUK;
        }

        boolean isSubscriptionPersoEnabled() {
            return this == APPSTATE_SUBSCRIPTION_PERSO;
        }

        boolean isAppReady() {
            return this == APPSTATE_READY;
        }

        boolean isAppNotReady() {
            if (this == APPSTATE_UNKNOWN || this == APPSTATE_DETECTED) {
                return true;
            }
            return false;
        }
    }

    public enum AppType {

        APPTYPE_UNKNOWN,
        APPTYPE_SIM,
        APPTYPE_USIM,
        APPTYPE_RUIM,
        APPTYPE_CSIM,
        APPTYPE_ISIM
    }

    public enum PersoSubState {

        PERSOSUBSTATE_UNKNOWN,
        PERSOSUBSTATE_IN_PROGRESS,
        PERSOSUBSTATE_READY,
        PERSOSUBSTATE_SIM_NETWORK,
        PERSOSUBSTATE_SIM_NETWORK_SUBSET,
        PERSOSUBSTATE_SIM_CORPORATE,
        PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
        PERSOSUBSTATE_SIM_SIM,
        PERSOSUBSTATE_SIM_NETWORK_PUK,
        PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
        PERSOSUBSTATE_SIM_CORPORATE_PUK,
        PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
        PERSOSUBSTATE_SIM_SIM_PUK,
        PERSOSUBSTATE_RUIM_NETWORK1,
        PERSOSUBSTATE_RUIM_NETWORK2,
        PERSOSUBSTATE_RUIM_HRPD,
        PERSOSUBSTATE_RUIM_CORPORATE,
        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
        PERSOSUBSTATE_RUIM_RUIM,
        PERSOSUBSTATE_RUIM_NETWORK1_PUK,
        PERSOSUBSTATE_RUIM_NETWORK2_PUK,
        PERSOSUBSTATE_RUIM_HRPD_PUK,
        PERSOSUBSTATE_RUIM_CORPORATE_PUK,
        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
        PERSOSUBSTATE_RUIM_RUIM_PUK;

        boolean isPersoSubStateUnknown() {
            return this == PERSOSUBSTATE_UNKNOWN;
        }
    }

    public AppType AppTypeFromRILInt(int type) {
        switch(type) {
            case 0:
                return AppType.APPTYPE_UNKNOWN;
            case 1:
                return AppType.APPTYPE_SIM;
            case 2:
                return AppType.APPTYPE_USIM;
            case 3:
                return AppType.APPTYPE_RUIM;
            case 4:
                return AppType.APPTYPE_CSIM;
            case 5:
                return AppType.APPTYPE_ISIM;
            default:
                AppType newType = AppType.APPTYPE_UNKNOWN;
                loge("AppTypeFromRILInt: bad RIL_AppType: " + type + " use APPTYPE_UNKNOWN");
                return newType;
        }
    }

    public AppState AppStateFromRILInt(int state) {
        switch(state) {
            case 0:
                return AppState.APPSTATE_UNKNOWN;
            case 1:
                return AppState.APPSTATE_DETECTED;
            case 2:
                return AppState.APPSTATE_PIN;
            case 3:
                return AppState.APPSTATE_PUK;
            case 4:
                return AppState.APPSTATE_SUBSCRIPTION_PERSO;
            case 5:
                return AppState.APPSTATE_READY;
            default:
                AppState newState = AppState.APPSTATE_UNKNOWN;
                loge("AppStateFromRILInt: bad state: " + state + " use APPSTATE_UNKNOWN");
                return newState;
        }
    }

    public PersoSubState PersoSubstateFromRILInt(int substate) {
        switch(substate) {
            case 0:
                return PersoSubState.PERSOSUBSTATE_UNKNOWN;
            case 1:
                return PersoSubState.PERSOSUBSTATE_IN_PROGRESS;
            case 2:
                return PersoSubState.PERSOSUBSTATE_READY;
            case 3:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK;
            case 4:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET;
            case 5:
                return PersoSubState.PERSOSUBSTATE_SIM_CORPORATE;
            case 6:
                return PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER;
            case 7:
                return PersoSubState.PERSOSUBSTATE_SIM_SIM;
            case 8:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_PUK;
            case 9:
                return PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK;
            case 10:
                return PersoSubState.PERSOSUBSTATE_SIM_CORPORATE_PUK;
            case 11:
                return PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK;
            case 12:
                return PersoSubState.PERSOSUBSTATE_SIM_SIM_PUK;
            case 13:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1;
            case 14:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2;
            case 15:
                return PersoSubState.PERSOSUBSTATE_RUIM_HRPD;
            case 16:
                return PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE;
            case 17:
                return PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER;
            case 18:
                return PersoSubState.PERSOSUBSTATE_RUIM_RUIM;
            case 19:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1_PUK;
            case 20:
                return PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2_PUK;
            case 21:
                return PersoSubState.PERSOSUBSTATE_RUIM_HRPD_PUK;
            case 22:
                return PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE_PUK;
            case 23:
                return PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK;
            case 24:
                return PersoSubState.PERSOSUBSTATE_RUIM_RUIM_PUK;
            default:
                PersoSubState newSubState = PersoSubState.PERSOSUBSTATE_UNKNOWN;
                loge("PersoSubstateFromRILInt: bad substate: " + substate + " use PERSOSUBSTATE_UNKNOWN");
                return newSubState;
        }
    }

    public PinState PinStateFromRILInt(int state) {
        switch(state) {
            case 0:
                return PinState.PINSTATE_UNKNOWN;
            case 1:
                return PinState.PINSTATE_ENABLED_NOT_VERIFIED;
            case 2:
                return PinState.PINSTATE_ENABLED_VERIFIED;
            case 3:
                return PinState.PINSTATE_DISABLED;
            case 4:
                return PinState.PINSTATE_ENABLED_BLOCKED;
            case 5:
                return PinState.PINSTATE_ENABLED_PERM_BLOCKED;
            default:
                PinState newPinState = PinState.PINSTATE_UNKNOWN;
                loge("PinStateFromRILInt: bad pin state: " + state + " use PINSTATE_UNKNOWN");
                return newPinState;
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{").append(this.app_type).append(",").append(this.app_state);
        if (this.app_state == AppState.APPSTATE_SUBSCRIPTION_PERSO) {
            sb.append(",").append(this.perso_substate);
        }
        if (!(this.app_type == AppType.APPTYPE_CSIM || this.app_type == AppType.APPTYPE_USIM)) {
            if (this.app_type == AppType.APPTYPE_ISIM) {
            }
            sb.append("}");
            return sb.toString();
        }
        sb.append(",pin1=").append(this.pin1);
        sb.append(",pin2=").append(this.pin2);
        sb.append(

        return sb.toString();
    }

    private void loge(String s) {
        Rlog.e("IccCardApplicationStatus", s);
    }
}


@Override
    public boolean apply(Game game, Ability source)

package mage.cards.t;

import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.choices.Choice;
import mage.choices.ChoiceCreatureType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;

/**
 * @author fireshoes
 */
public final class TsabosDecree extends CardImpl {

    public TsabosDecree(UUID ownerId, CardSetInfo setInfo) {
        super(ownerId, setInfo, new CardType[] { CardType.INSTANT }, "{5}{B}");
        // Choose a creature type. Target player reveals their hand and discards all creature cards of that type. Then destroy all creatures of that type that player controls. They can't be regenerated.
        this.getSpellAbility().addEffect(new TsabosDecreeEffect());
        this.getSpellAbility().addTarget(new TargetPlayer());
    }

    private TsabosDecree(final TsabosDecree card) {
        super(card);
    }

    @Override
    public TsabosDecree copy() {
        return new TsabosDecree(this);
    }
}

class TsabosDecreeEffect extends OneShotEffect {

    TsabosDecreeEffect() {
        super(Outcome.UnboostCreature);
        staticText = "Choose a creature type. Target player reveals their hand and discards " + "all creature cards of that type. Then destroy all creatures of that type that player controls. " + "They can't be regenerated";
    }

    private TsabosDecreeEffect(final TsabosDecreeEffect effect) {
        super(effect);
    }

{
        Player player = game.getPlayer(source.getControllerId());
        Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
        MageObject sourceObject = game.getObject(source.getSourceId());
        if (player == null) {
            return false;
        }
        if (sourceObject == null) {
            return false;
        }
        Choice typeChoice = new ChoiceCreatureType(sourceObject);
        if (!player.choose(outcome, typeChoice, game)) {
            return false;
        }
        game.informPlayers(sourceObject.getLogName() + " chosen type: " + typeChoice.getChoice());
        targetPlayer.revealCards("hand of " + targetPlayer.getName(), targetPlayer.getHand(), game);
        FilterCard filterCard = new FilterCard();
        filterCard.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
        targetPlayer.discard(new CardsImpl(targetPlayer.getHand().getCards(filterCard, game)), false, source, game);
        FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent();
        filterCreaturePermanent.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
        for (Permanent creature : game.getBattlefield().getActivePermanents(filterCreaturePermanent, source.getSourceId(), game)) {
            if (creature.isControlledBy(targetPlayer.getId())) {
                creature.destroy(source, game, true);
            }
        }
        return true;
    }

    @Override
    public TsabosDecreeEffect copy() {
        return new TsabosDecreeEffect(this);
    }
}


{
        return new TsabosDecreeEffect(this);
    }

package mage.cards.t;

import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.choices.Choice;
import mage.choices.ChoiceCreatureType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;

/**
 * @author fireshoes
 */
public final class TsabosDecree extends CardImpl {

    public TsabosDecree(UUID ownerId, CardSetInfo setInfo) {
        super(ownerId, setInfo, new CardType[] { CardType.INSTANT }, "{5}{B}");
        // Choose a creature type. Target player reveals their hand and discards all creature cards of that type. Then destroy all creatures of that type that player controls. They can't be regenerated.
        this.getSpellAbility().addEffect(new TsabosDecreeEffect());
        this.getSpellAbility().addTarget(new TargetPlayer());
    }

    private TsabosDecree(final TsabosDecree card) {
        super(card);
    }

    @Override
    public TsabosDecree copy() {
        return new TsabosDecree(this);
    }
}

class TsabosDecreeEffect extends OneShotEffect {

    TsabosDecreeEffect() {
        super(Outcome.UnboostCreature);
        staticText = "Choose a creature type. Target player reveals their hand and discards " + "all creature cards of that type. Then destroy all creatures of that type that player controls. " + "They can't be regenerated";
    }

    private TsabosDecreeEffect(final TsabosDecreeEffect effect) {
        super(effect);
    }

    @Override
    public boolean apply(Game game, Ability source) {
        Player player = game.getPlayer(source.getControllerId());
        Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
        MageObject sourceObject = game.getObject(source.getSourceId());
        if (player == null) {
            return false;
        }
        if (sourceObject == null) {
            return false;
        }
        Choice typeChoice = new ChoiceCreatureType(sourceObject);
        if (!player.choose(outcome, typeChoice, game)) {
            return false;
        }
        game.informPlayers(sourceObject.getLogName() + " chosen type: " + typeChoice.getChoice());
        targetPlayer.revealCards("hand of " + targetPlayer.getName(), targetPlayer.getHand(), game);
        FilterCard filterCard = new FilterCard();
        filterCard.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
        targetPlayer.discard(new CardsImpl(targetPlayer.getHand().getCards(filterCard, game)), false, source, game);
        FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent();
        filterCreaturePermanent.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
        for (Permanent creature : game.getBattlefield().getActivePermanents(filterCreaturePermanent, source.getSourceId(), game)) {
            if (creature.isControlledBy(targetPlayer.getId())) {
                creature.destroy(source, game, true);
            }
        }
        return true;
    }

    @Override
    public TsabosDecreeEffect copy()


.getHand().getCards(filterCard, game)), false, source, game);

package mage.cards.t;

import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.choices.Choice;
import mage.choices.ChoiceCreatureType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;

/**
 * @author fireshoes
 */
public final class TsabosDecree extends CardImpl {

    public TsabosDecree(UUID ownerId, CardSetInfo setInfo) {
        super(ownerId, setInfo, new CardType[] { CardType.INSTANT }, "{5}{B}");
        // Choose a creature type. Target player reveals their hand and discards all creature cards of that type. Then destroy all creatures of that type that player controls. They can't be regenerated.
        this.getSpellAbility().addEffect(new TsabosDecreeEffect());
        this.getSpellAbility().addTarget(new TargetPlayer());
    }

    private TsabosDecree(final TsabosDecree card) {
        super(card);
    }

    @Override
    public TsabosDecree copy() {
        return new TsabosDecree(this);
    }
}

class TsabosDecreeEffect extends OneShotEffect {

    TsabosDecreeEffect() {
        super(Outcome.UnboostCreature);
        staticText = "Choose a creature type. Target player reveals their hand and discards " + "all creature cards of that type. Then destroy all creatures of that type that player controls. " + "They can't be regenerated";
    }

    private TsabosDecreeEffect(final TsabosDecreeEffect effect) {
        super(effect);
    }

    @Override
    public boolean apply(Game game, Ability source) {
        Player player = game.getPlayer(source.getControllerId());
        Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
        MageObject sourceObject = game.getObject(source.getSourceId());
        if (player == null) {
            return false;
        }
        if (sourceObject == null) {
            return false;
        }
        Choice typeChoice = new ChoiceCreatureType(sourceObject);
        if (!player.choose(outcome, typeChoice, game)) {
            return false;
        }
        game.informPlayers(sourceObject.getLogName() + " chosen type: " + typeChoice.getChoice());
        targetPlayer.revealCards("hand of " + targetPlayer.getName(), targetPlayer.getHand(), game);
        FilterCard filterCard = new FilterCard();
        filterCard.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
        targetPlayer.discard(new CardsImpl(targetPlayer

        FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent();
        filterCreaturePermanent.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
        for (Permanent creature : game.getBattlefield().getActivePermanents(filterCreaturePermanent, source.getSourceId(), game)) {
            if (creature.isControlledBy(targetPlayer.getId())) {
                creature.destroy(source, game, true);
            }
        }
        return true;
    }

    @Override
    public TsabosDecreeEffect copy() {
        return new TsabosDecreeEffect(this);
    }
}


@Override
        public String toString()

package com.couchbase.connect.kafka.handler.sink;

import java.util.HashSet;
import java.util.Objects;
import static java.util.Objects.requireNonNull;

/**
 * Used for concurrency control. Determines which actions may
 * be performed concurrently.
 *

 * If two actions have concurrency hints with equal values,
 * the first action must complete before the second is started.
 *

 * Example: Using document IDs as hint values is a way to express
 * the constraint that different documents may be updated in parallel,
 * but updates to the same document must be applied sequentially.
 *
 * @see #of(Object)
 * @see #alwaysConcurrent()
 * @see #neverConcurrent()
 */
public class ConcurrencyHint {

    /**
     * Indicates the action may be performed concurrently with any other action
     * whose hint value is NOT EQUAL to this one.
     *
     * @param value the value that must be unique withing a batch of concurrent operations.
     * Must be the sort of thing you can safely insert in a {@link HashSet}.
     */
    public static ConcurrencyHint of(Object value) {
        return new ConcurrencyHint(value);
    }

    /**
     * Returns a special hint indicating the action may be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     */
    public static ConcurrencyHint alwaysConcurrent() {
        return ALWAYS_CONCURRENT;
    }

    /**
     * Returns a special hint indicating the action must never be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     *

     * In other words, all prior actions will be completed before this action is performed,
     * and this action will be completed before any subsequent actions are performed.
     *

     * Takes precedence over {@link #alwaysConcurrent()}.
     */
    public static ConcurrencyHint neverConcurrent() {
        return NEVER_CONCURRENT;
    }

    private final Object value;

    private static final ConcurrencyHint NEVER_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint.NEVER_CONCURRENT";
        }
    };

    private static final ConcurrencyHint ALWAYS_CONCURRENT = new ConcurrencyHint(new Object()) {

{
            return "ConcurrencyHint.ALWAYS_CONCURRENT";
        }
    };

    private ConcurrencyHint(Object value) {
        this.value = requireNonNull(value);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ConcurrencyHint that = (ConcurrencyHint) o;
        return value.equals(that.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    @Override
    public String toString() {
        return "ConcurrencyHint{" + "value=" + value + '}';
    }
}


{
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ConcurrencyHint that = (ConcurrencyHint) o;
        return value.equals(that.value);
    }

package com.couchbase.connect.kafka.handler.sink;

import java.util.HashSet;
import java.util.Objects;
import static java.util.Objects.requireNonNull;

/**
 * Used for concurrency control. Determines which actions may
 * be performed concurrently.
 *

 * If two actions have concurrency hints with equal values,
 * the first action must complete before the second is started.
 *

 * Example: Using document IDs as hint values is a way to express
 * the constraint that different documents may be updated in parallel,
 * but updates to the same document must be applied sequentially.
 *
 * @see #of(Object)
 * @see #alwaysConcurrent()
 * @see #neverConcurrent()
 */
public class ConcurrencyHint {

    /**
     * Indicates the action may be performed concurrently with any other action
     * whose hint value is NOT EQUAL to this one.
     *
     * @param value the value that must be unique withing a batch of concurrent operations.
     * Must be the sort of thing you can safely insert in a {@link HashSet}.
     */
    public static ConcurrencyHint of(Object value) {
        return new ConcurrencyHint(value);
    }

    /**
     * Returns a special hint indicating the action may be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     */
    public static ConcurrencyHint alwaysConcurrent() {
        return ALWAYS_CONCURRENT;
    }

    /**
     * Returns a special hint indicating the action must never be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     *

     * In other words, all prior actions will be completed before this action is performed,
     * and this action will be completed before any subsequent actions are performed.
     *

     * Takes precedence over {@link #alwaysConcurrent()}.
     */
    public static ConcurrencyHint neverConcurrent() {
        return NEVER_CONCURRENT;
    }

    private final Object value;

    private static final ConcurrencyHint NEVER_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint.NEVER_CONCURRENT";
        }
    };

    private static final ConcurrencyHint ALWAYS_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint.ALWAYS_CONCURRENT";
        }
    };

    private ConcurrencyHint(Object value) {
        this.value = requireNonNull(value);
    }

    @Override
    public boolean equals(Object o)

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    @Override
    public String toString() {
        return "ConcurrencyHint{" + "value=" + value + '}';
    }
}


package com.couchbase.connect.kafka.handler.sink;

import java.util.HashSet;
import java.util.Objects;
import static java.util.Objects.requireNonNull;

/**
 * Used for concurrency control. Determines which actions may
 * be performed concurrently.
 *

 * If two actions have concurrency hints with equal values,
 * the first action must complete before the second is started.
 *

 * Example: Using document IDs as hint values is a way to express
 * the constraint that different documents may be updated in parallel,
 * but updates to the same document must be applied sequentially.
 *
 * @see #of(Object)
 * @see #alwaysConcurrent()
 * @see #neverConcurrent()
 */
public class ConcurrencyHint {

    /**
     * Indicates the action may be performed concurrently with any other action
     * whose hint value is NOT EQUAL to this one.
     *
     * @param value the value that must be unique withing a batch of concurrent operations.
     * Must be the sort of thing you can safely insert in a {@link HashSet}.
     */
    public static ConcurrencyHint of(Object value) {
        return new ConcurrencyHint(value);
    }

    /**
     * Returns a special hint indicating the action may be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     */
    public static ConcurrencyHint alwaysConcurrent() {
        return ALWAYS_CONCURRENT;
    }

    /**
     * Returns a special hint indicating the action must never be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     *

     * In other words, all prior actions will be completed before this action is performed,
     * and this action will be completed before any subsequent actions are performed.
     *

     * Takes precedence over {@link #alwaysConcurrent()}.
     */
    public static ConcurrencyHint neverConcurrent() {
        return NEVER_CONCURRENT;
    }

    private final Object value;

    private static final ConcurrencyHint NEVER_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint.NEVER_CONCURRENT";
        }
    };

    private static final ConcurrencyHint ALWAYS_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint

        }
    };

    private ConcurrencyHint(Object value) {
        this.value = requireNonNull(value);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ConcurrencyHint that = (ConcurrencyHint) o;
        return value.equals(that.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    @Override
    public String toString() {
        return "ConcurrencyHint{" + "value=" + value + '}';
    }
}


public static ConcurrencyHint alwaysConcurrent() {
        return ALWAYS_CONCURRENT;
    }

package com.couchbase.connect.kafka.handler.sink;

import java.util.HashSet;
import java.util.Objects;
import static java.util.Objects.requireNonNull;

/**
 * Used for concurrency control. Determines which actions may
 * be performed concurrently.
 *

 * If two actions have concurrency hints with equal values,
 * the first action must complete before the second is started.
 *

 * Example: Using document IDs as hint values is a way to express
 * the constraint that different documents may be updated in parallel,
 * but updates to the same document must be applied sequentially.
 *
 * @see #of(Object)
 * @see #alwaysConcurrent()
 * @see #neverConcurrent()
 */
public class ConcurrencyHint {

    /**
     * Indicates the action may be performed concurrently with any other action
     * whose hint value is NOT EQUAL to this one.
     *
     * @param value the value that must be unique withing a batch of concurrent operations.
     * Must be the sort of thing you can safely insert in a {@link HashSet}.
     */
    public static ConcurrencyHint of(Object value) {
        return new ConcurrencyHint(value);
    }

    /**
     * Returns a special hint indicating the action may be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     */

/**
     * Returns a special hint indicating the action must never be performed concurrently
     * with any other action, regardless of the other action's concurrency hint.
     *

     * In other words, all prior actions will be completed before this action is performed,
     * and this action will be completed before any subsequent actions are performed.
     *

     * Takes precedence over {@link #alwaysConcurrent()}.
     */
    public static ConcurrencyHint neverConcurrent() {
        return NEVER_CONCURRENT;
    }

    private final Object value;

    private static final ConcurrencyHint NEVER_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint.NEVER_CONCURRENT";
        }
    };

    private static final ConcurrencyHint ALWAYS_CONCURRENT = new ConcurrencyHint(new Object()) {

        @Override
        public String toString() {
            return "ConcurrencyHint.ALWAYS_CONCURRENT";
        }
    };

    private ConcurrencyHint(Object value) {
        this.value = requireNonNull(value);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ConcurrencyHint that = (ConcurrencyHint) o;
        return value.equals(that.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    @Override
    public String toString() {
        return "ConcurrencyHint{" + "value=" + value + '}';
    }
}


/*
 * This file is part of Quelea, free projection software for churches.
 *
 *
 */
package org.quelea.data.bible;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.quelea.data.displayable.BiblePassage;
import org.quelea.services.languages.LabelGrabber;
import org.quelea.services.utils.QueleaProperties;
import org.quelea.windows.main.QueleaApp;
import org.quelea.windows.main.widgets.LoadingPane;

/**
 * A dialog that can be used for searching for bible passages.
 * <p/>
 * @author mjrb5
 */
public class BibleSearchDialog extends Stage implements BibleChangeListener {

    private TextField searchField;

    private BibleSearchTreeView searchResults;

    private ComboBox<String> bibles;

    private ScrollPane scrollPane;

    private LoadingPane overlay;

    private FlowPane chapterPane;

    private final Button addToSchedule;

    private final Text resultsField;

    /**
     * Create a new bible searcher dialog.
     */
    public BibleSearchDialog() {
        BorderPane mainPane = new BorderPane();
        setTitle(LabelGrabber.INSTANCE.getLabel("bible.search.title"));
        getIcons().add(new Image("file:icons/search.png"));
        overlay = new LoadingPane();
        searchField = new TextField();
        bibles = new ComboBox<>();
        bibles.setEditable(false);
        chapterPane = new FlowPane();
        scrollPane = new ScrollPane();
        scrollPane.setContent(chapterPane);
        searchResults = new BibleSearchTreeView(scrollPane, bibles);
        resultsField = new Text(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        resultsField.setFont(Font.font("Sans", 14));
        resultsField.getStyleClass().add("text");
        addToSchedule = new Button(LabelGrabber.INSTANCE.getLabel("add.to.schedule.text"), new ImageView(new Image("file:icons/tick.png")));
        BibleManager.get().registerBibleChangeListener(this);
        updateBibles();
        // top panel
        HBox northPanel = new HBox();
        northPanel.setPadding(new Insets(5, 5, 5, 5));
        northPanel.getChildren().addAll(bibles, searchField, addToSchedule, resultsField);
        mainPane.setTop(northPanel);
        // center panel
        StackPane searchPane = new StackPane();
        searchPane.getChildren().addAll(searchResults, overlay);
        SplitPane centerPanel = new SplitPane();
        centerPanel.setDividerPosition(0, 0.3);
        centerPanel.getItems().addAll(searchPane, scrollPane);
        mainPane.setCenter(centerPanel);
        // Sizing
        this.setHeight(600);
        this.setWidth(800);
        this.setMinHeight(300);
        this.setMinWidth(500);
        // Event handlers
        bibles.setOnAction((javafx.event.ActionEvent t) -> {
            searchResults.resetRoot();
            update();
        });
        searchField.textProperty().addListener((ObservableValue<? extends String> ov, String t, String t1) -> {
            update();
        });
        addToSchedule.setOnAction((ActionEvent t) -> {
            if (searchResults.getSelectionModel().getSelectedItem().getValue() instanceof BibleVerse) {
                BibleChapter chap = (BibleChapter) searchResults.getSelectionModel().getSelectedItem().getValue().getParent();
                Bible bib = (Bible) chap.getParent().getParent();
                BiblePassage passage = new BiblePassage(bib.getBibleName(), chap.getBook() + " " + chap.toString(), chap.getVerses(), false);
                QueleaApp.get().getMainWindow().getMainPanel().getSchedulePanel().getScheduleList().add(passage);
            }
        });
        setOnShown((WindowEvent event) -> {
            if (!BibleManager.get().isIndexInit()) {
                BibleManager.get().refreshAndLoad();
            }
        });
        reset();
        Scene scene = new Scene(mainPane);
        if (QueleaProperties.get().getUseDarkTheme()) {
            scene.getStylesheets().add("org/modena_dark.css");
        }
        setScene(scene);
    }

    public final void reset() {
        searchField.setText(LabelGrabber.INSTANCE.getLabel("initial.search.text"));
        searchField.focusedProperty().addListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (t1) {
                    searchField.setText("");
                    searchField.focusedProperty().removeListener(this);
                }
            }
        });
        searchField.setDisable(true);
        BibleManager.get().runOnIndexInit(() -> {
            searchField.setDisable(false);
        });
    }

    private ExecutorService updateExecutor = Executors.newSingleThreadExecutor();

    private ExecRunnable lastUpdateRunnable = null;

    private interface ExecRunnable extends Runnable {

        void cancel();
    }

    /**
     * Update the results based on the entered text.
     */
    private void update() {
        final String text = searchField.getText();
        if (text.length() > 3) {
            if (BibleManager.get().isIndexInit()) {
                searchResults.reset();
                overlay.show();
                ExecRunnable execRunnable = new ExecRunnable() {

                    private volatile boolean cancel = false;

{
                        cancel = true;
                    }

                    public void run() {
                        if (cancel) {
                            return;
                        }
                        final BibleChapter[] results = BibleManager.get().getIndex().filter(text, null);
                        Platform.runLater(() -> {
                            searchResults.reset();
                            if (!text.trim().isEmpty()) {
                                for (BibleChapter chapter : results) {
                                    if (bibles.getSelectionModel().getSelectedIndex() == 0 || chapter.getBook().getBible().getName().equals(bibles.getSelectionModel().getSelectedItem())) {
                                        for (BibleVerse verse : chapter.getVerses()) {
                                            if (verse.getText().toLowerCase().contains(text.toLowerCase())) {
                                                searchResults.add(verse);
                                            }
                                        }
                                    }
                                }
                            }
                            overlay.hide();
                            String resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.results.found");
                            if (searchResults.size() == 1 && LabelGrabber.INSTANCE.isLocallyDefined("bible.search.result.found")) {
                                resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.result.found");
                            }
                            resultsField.setText(" " + searchResults.size() + " " + resultsfoundSuffix);
                        });
                    }
                };
                if (lastUpdateRunnable != null) {
                    lastUpdateRunnable.cancel();
                }
                lastUpdateRunnable = execRunnable;
                updateExecutor.submit(execRunnable);
            }
        }
        searchResults.reset();
        resultsField.setText(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        chapterPane.getChildren().clear();
    }

    /**
     * Update the list of bibles on this search dialog.
     */
    @Override
    public final void updateBibles() {
        bibles.itemsProperty().get().clear();
        bibles.itemsProperty().get().add(LabelGrabber.INSTANCE.getLabel("all.text"));
        for (Bible bible : BibleManager.get().getBibles()) {
            bibles.itemsProperty().get().add(bible.getName());
        }
        bibles.getSelectionModel().selectFirst();
    }
}


{
                        cancel = true;
                    }

/*
 * This file is part of Quelea, free projection software for churches.
 *
 *
 */
package org.quelea.data.bible;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.quelea.data.displayable.BiblePassage;
import org.quelea.services.languages.LabelGrabber;
import org.quelea.services.utils.QueleaProperties;
import org.quelea.windows.main.QueleaApp;
import org.quelea.windows.main.widgets.LoadingPane;

/**
 * A dialog that can be used for searching for bible passages.
 * <p/>
 * @author mjrb5
 */
public class BibleSearchDialog extends Stage implements BibleChangeListener {

    private TextField searchField;

    private BibleSearchTreeView searchResults;

    private ComboBox<String> bibles;

    private ScrollPane scrollPane;

    private LoadingPane overlay;

    private FlowPane chapterPane;

    private final Button addToSchedule;

    private final Text resultsField;

    /**
     * Create a new bible searcher dialog.
     */
    public BibleSearchDialog() {
        BorderPane mainPane = new BorderPane();
        setTitle(LabelGrabber.INSTANCE.getLabel("bible.search.title"));
        getIcons().add(new Image("file:icons/search.png"));
        overlay = new LoadingPane();
        searchField = new TextField();
        bibles = new ComboBox<>();
        bibles.setEditable(false);
        chapterPane = new FlowPane();
        scrollPane = new ScrollPane();
        scrollPane.setContent(chapterPane);
        searchResults = new BibleSearchTreeView(scrollPane, bibles);
        resultsField = new Text(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        resultsField.setFont(Font.font("Sans", 14));
        resultsField.getStyleClass().add("text");
        addToSchedule = new Button(LabelGrabber.INSTANCE.getLabel("add.to.schedule.text"), new ImageView(new Image("file:icons/tick.png")));
        BibleManager.get().registerBibleChangeListener(this);
        updateBibles();
        // top panel
        HBox northPanel = new HBox();
        northPanel.setPadding(new Insets(5, 5, 5, 5));
        northPanel.getChildren().addAll(bibles, searchField, addToSchedule, resultsField);
        mainPane.setTop(northPanel);
        // center panel
        StackPane searchPane = new StackPane();
        searchPane.getChildren().addAll(searchResults, overlay);
        SplitPane centerPanel = new SplitPane();
        centerPanel.setDividerPosition(0, 0.3);
        centerPanel.getItems().addAll(searchPane, scrollPane);
        mainPane.setCenter(centerPanel);
        // Sizing
        this.setHeight(600);
        this.setWidth(800);
        this.setMinHeight(300);
        this.setMinWidth(500);
        // Event handlers
        bibles.setOnAction((javafx.event.ActionEvent t) -> {
            searchResults.resetRoot();
            update();
        });
        searchField.textProperty().addListener((ObservableValue<? extends String> ov, String t, String t1) -> {
            update();
        });
        addToSchedule.setOnAction((ActionEvent t) -> {
            if (searchResults.getSelectionModel().getSelectedItem().getValue() instanceof BibleVerse) {
                BibleChapter chap = (BibleChapter) searchResults.getSelectionModel().getSelectedItem().getValue().getParent();
                Bible bib = (Bible) chap.getParent().getParent();
                BiblePassage passage = new BiblePassage(bib.getBibleName(), chap.getBook() + " " + chap.toString(), chap.getVerses(), false);
                QueleaApp.get().getMainWindow().getMainPanel().getSchedulePanel().getScheduleList().add(passage);
            }
        });
        setOnShown((WindowEvent event) -> {
            if (!BibleManager.get().isIndexInit()) {
                BibleManager.get().refreshAndLoad();
            }
        });
        reset();
        Scene scene = new Scene(mainPane);
        if (QueleaProperties.get().getUseDarkTheme()) {
            scene.getStylesheets().add("org/modena_dark.css");
        }
        setScene(scene);
    }

    public final void reset() {
        searchField.setText(LabelGrabber.INSTANCE.getLabel("initial.search.text"));
        searchField.focusedProperty().addListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (t1) {
                    searchField.setText("");
                    searchField.focusedProperty().removeListener(this);
                }
            }
        });
        searchField.setDisable(true);
        BibleManager.get().runOnIndexInit(() -> {
            searchField.setDisable(false);
        });
    }

    private ExecutorService updateExecutor = Executors.newSingleThreadExecutor();

    private ExecRunnable lastUpdateRunnable = null;

    private interface ExecRunnable extends Runnable {

        void cancel();
    }

    /**
     * Update the results based on the entered text.
     */
    private void update() {
        final String text = searchField.getText();
        if (text.length() > 3) {
            if (BibleManager.get().isIndexInit()) {
                searchResults.reset();
                overlay.show();
                ExecRunnable execRunnable = new ExecRunnable() {

                    private volatile boolean cancel = false;

                    public void cancel()

                    public void run() {
                        if (cancel) {
                            return;
                        }
                        final BibleChapter[] results = BibleManager.get().getIndex().filter(text, null);
                        Platform.runLater(() -> {
                            searchResults.reset();
                            if (!text.trim().isEmpty()) {
                                for (BibleChapter chapter : results) {
                                    if (bibles.getSelectionModel().getSelectedIndex() == 0 || chapter.getBook().getBible().getName().equals(bibles.getSelectionModel().getSelectedItem())) {
                                        for (BibleVerse verse : chapter.getVerses()) {
                                            if (verse.getText().toLowerCase().contains(text.toLowerCase())) {
                                                searchResults.add(verse);
                                            }
                                        }
                                    }
                                }
                            }
                            overlay.hide();
                            String resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.results.found");
                            if (searchResults.size() == 1 && LabelGrabber.INSTANCE.isLocallyDefined("bible.search.result.found")) {
                                resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.result.found");
                            }
                            resultsField.setText(" " + searchResults.size() + " " + resultsfoundSuffix);
                        });
                    }
                };
                if (lastUpdateRunnable != null) {
                    lastUpdateRunnable.cancel();
                }
                lastUpdateRunnable = execRunnable;
                updateExecutor.submit(execRunnable);
            }
        }
        searchResults.reset();
        resultsField.setText(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        chapterPane.getChildren().clear();
    }

    /**
     * Update the list of bibles on this search dialog.
     */
    @Override
    public final void updateBibles() {
        bibles.itemsProperty().get().clear();
        bibles.itemsProperty().get().add(LabelGrabber.INSTANCE.getLabel("all.text"));
        for (Bible bible : BibleManager.get().getBibles()) {
            bibles.itemsProperty().get().add(bible.getName());
        }
        bibles.getSelectionModel().selectFirst();
    }
}


/*
 * This file is part of Quelea, free projection software for churches.
 *
 *
 */
package org.quelea.data.bible;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.quelea.data.displayable.BiblePassage;
import org.quelea.services.languages.LabelGrabber;
import org.quelea.services.utils.QueleaProperties;
import org.quelea.windows.main.QueleaApp;
import org.quelea.windows.main.widgets.LoadingPane;

/**
 * A dialog that can be used for searching for bible passages.
 * <p/>
 * @author mjrb5
 */
public class BibleSearchDialog extends Stage implements BibleChangeListener {

    private TextField searchField;

    private BibleSearchTreeView searchResults;

    private ComboBox<String> bibles;

    private ScrollPane scrollPane;

    private LoadingPane overlay;

    private FlowPane chapterPane;

    private final Button addToSchedule;

    private final Text resultsField;

    /**
     * Create a new bible searcher dialog.
     */
    public BibleSearchDialog() {
        BorderPane mainPane = new BorderPane();
        setTitle(LabelGrabber.INSTANCE.getLabel("bible.search.title"));
        getIcons().add(new Image("file:icons/search.png"));
        overlay = new LoadingPane();
        searchField = new TextField();
        bibles = new ComboBox<>();
        bibles.setEditable(false);
        chapterPane = new FlowPane();
        scrollPane = new ScrollPane();
        scrollPane.setContent(chapterPane);
        searchResults = new BibleSearchTreeView(scrollPane, bibles);
        resultsField = new Text(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        resultsField.setFont(Font.font("Sans", 14));
        resultsField.getStyleClass().add("text");
        addToSchedule = new Button(LabelGrabber.INSTANCE.getLabel("add.to.schedule.text"), new ImageView(new Image("file:icons/tick.png")));
        BibleManager.get().registerBibleChangeListener(this);
        updateBibles();
        // top panel
        HBox northPanel = new HBox();
        northPanel.setPadding(new Insets(5, 5, 5, 5));
        northPanel.getChildren().addAll(bibles, searchField, addToSchedule, resultsField);
        mainPane.setTop(northPanel);
        // center panel
        StackPane searchPane = new StackPane();
        searchPane.getChildren().addAll(searchResults, overlay);
        SplitPane centerPanel = new SplitPane();
        centerPanel.setDividerPosition(0, 0.3);
        centerPanel.getItems().addAll(searchPane, scrollPane);
        mainPane.setCenter(centerPanel);
        // Sizing
        this.setHeight(600);
        this.setWidth(800);
        this.setMinHeight(300);
        this.setMinWidth(500);
        // Event handlers
        bibles.setOnAction((javafx.event.ActionEvent t) -> {
            searchResults.resetRoot();
            update();
        });
        searchField.textProperty().addListener((ObservableValue<? extends String> ov, String t, String t1) -> {
            update();
        });
        addToSchedule.setOnAction((ActionEvent t) -> {
            if (searchResults.getSelectionModel().getSelectedItem().getValue() instanceof BibleVerse) {
                BibleChapter chap = (BibleChapter) searchResults.getSelectionModel().getSelectedItem().getValue().getParent();
                Bible bib = (Bible) chap.getParent().getParent();
                BiblePassage passage = new BiblePassage(bib.getBibleName(), chap.getBook() + " " + chap.toString(), chap.getVerses(), false);
                QueleaApp.get().getMainWindow().getMainPanel().getSchedulePanel().getScheduleList().add(passage);
            }
        });
        setOnShown((WindowEvent event) -> {
            if (!BibleManager.get().isIndexInit()) {
                BibleManager.get().refreshAndLoad();
            }
        });
        reset();
        Scene scene = new Scene(mainPane);
        if (QueleaProperties.get().getUseDarkTheme()) {
            scene.getStylesheets().add("org/modena_dark.css");
        }
        setScene(scene);
    }

    public final void reset() {
        searchField.setText(LabelGrabber.INSTANCE.getLabel("initial.search.text"));
        searchField.focusedProperty().addListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (t1) {
                    searchField.setText("");
                    searchField.focusedProperty().removeListener(this);
                }
            }
        });
        searchField.setDisable

        BibleManager.get().runOnIndexInit(() -> {
            searchField.setDisable(false);
        });
    }

    private ExecutorService updateExecutor = Executors.newSingleThreadExecutor();

    private ExecRunnable lastUpdateRunnable = null;

    private interface ExecRunnable extends Runnable {

        void cancel();
    }

    /**
     * Update the results based on the entered text.
     */
    private void update() {
        final String text = searchField.getText();
        if (text.length() > 3) {
            if (BibleManager.get().isIndexInit()) {
                searchResults.reset();
                overlay.show();
                ExecRunnable execRunnable = new ExecRunnable() {

                    private volatile boolean cancel = false;

                    public void cancel() {
                        cancel = true;
                    }

                    public void run() {
                        if (cancel) {
                            return;
                        }
                        final BibleChapter[] results = BibleManager.get().getIndex().filter(text, null);
                        Platform.runLater(() -> {
                            searchResults.reset();
                            if (!text.trim().isEmpty()) {
                                for (BibleChapter chapter : results) {
                                    if (bibles.getSelectionModel().getSelectedIndex() == 0 || chapter.getBook().getBible().getName().equals(bibles.getSelectionModel().getSelectedItem())) {
                                        for (BibleVerse verse : chapter.getVerses()) {
                                            if (verse.getText().toLowerCase().contains(text.toLowerCase())) {
                                                searchResults.add(verse);
                                            }
                                        }
                                    }
                                }
                            }
                            overlay.hide();
                            String resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.results.found");
                            if (searchResults.size() == 1 && LabelGrabber.INSTANCE.isLocallyDefined("bible.search.result.found")) {
                                resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.result.found");
                            }
                            resultsField.setText(" " + searchResults.size() + " " + resultsfoundSuffix);
                        });
                    }
                };
                if (lastUpdateRunnable != null) {
                    lastUpdateRunnable.cancel();
                }
                lastUpdateRunnable = execRunnable;
                updateExecutor.submit(execRunnable);
            }
        }
        searchResults.reset();
        resultsField.setText(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        chapterPane.getChildren().clear();
    }

    /**
     * Update the list of bibles on this search dialog.
     */
    @Override
    public final void updateBibles() {
        bibles.itemsProperty().get().clear();
        bibles.itemsProperty().get().add(LabelGrabber.INSTANCE.getLabel("all.text"));
        for (Bible bible : BibleManager.get().getBibles()) {
            bibles.itemsProperty().get().add(bible.getName());
        }
        bibles.getSelectionModel().selectFirst();
    }
}


@Override
    public final void updateBibles() {
        bibles.itemsProperty().get().clear();
        bibles.itemsProperty().get().add(LabelGrabber.INSTANCE.getLabel("all.text"));
        for (Bible bible : BibleManager.get().getBibles()) {
            bibles.itemsProperty().get().add(bible.getName());
        }
        bibles.getSelectionModel().selectFirst();
    }

/*
 * This file is part of Quelea, free projection software for churches.
 *
 *
 */
package org.quelea.data.bible;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.quelea.data.displayable.BiblePassage;
import org.quelea.services.languages.LabelGrabber;
import org.quelea.services.utils.QueleaProperties;
import org.quelea.windows.main.QueleaApp;
import org.quelea.windows.main.widgets.LoadingPane;

/**
 * A dialog that can be used for searching for bible passages.
 * <p/>
 * @author mjrb5
 */
public class BibleSearchDialog extends Stage implements BibleChangeListener {

    private TextField searchField;

    private BibleSearchTreeView searchResults;

    private ComboBox<String> bibles;

    private ScrollPane scrollPane;

    private LoadingPane overlay;

    private FlowPane chapterPane;

    private final Button addToSchedule;

    private final Text resultsField;

    /**
     * Create a new bible searcher dialog.
     */
    public BibleSearchDialog() {
        BorderPane mainPane = new BorderPane();
        setTitle(LabelGrabber.INSTANCE.getLabel("bible.search.title"));
        getIcons().add(new Image("file:icons/search.png"));
        overlay = new LoadingPane();
        searchField = new TextField();
        bibles = new ComboBox<>();
        bibles.setEditable(false);
        chapterPane = new FlowPane();
        scrollPane = new ScrollPane();
        scrollPane.setContent(chapterPane);
        searchResults = new BibleSearchTreeView(scrollPane, bibles);
        resultsField = new Text(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        resultsField.setFont(Font.font("Sans", 14));
        resultsField.getStyleClass().add("text");
        addToSchedule = new Button(LabelGrabber.INSTANCE.getLabel("add.to.schedule.text"), new ImageView(new Image("file:icons/tick.png")));
        BibleManager.get().registerBibleChangeListener(this);
        updateBibles();
        // top panel
        HBox northPanel = new HBox();
        northPanel.setPadding(new Insets(5, 5, 5, 5));
        northPanel.getChildren().addAll(bibles, searchField, addToSchedule, resultsField);
        mainPane.setTop(northPanel);
        // center panel
        StackPane searchPane = new StackPane();
        searchPane.getChildren().addAll(searchResults, overlay);
        SplitPane centerPanel = new SplitPane();
        centerPanel.setDividerPosition(0, 0.3);
        centerPanel.getItems().addAll(searchPane, scrollPane);
        mainPane.setCenter(centerPanel);
        // Sizing
        this.setHeight(600);
        this.setWidth(800);
        this.setMinHeight(300);
        this.setMinWidth(500);
        // Event handlers
        bibles.setOnAction((javafx.event.ActionEvent t) -> {
            searchResults.resetRoot();
            update();
        });
        searchField.textProperty().addListener((ObservableValue<? extends String> ov, String t, String t1) -> {
            update();
        });
        addToSchedule.setOnAction((ActionEvent t) -> {
            if (searchResults.getSelectionModel().getSelectedItem().getValue() instanceof BibleVerse) {
                BibleChapter chap = (BibleChapter) searchResults.getSelectionModel().getSelectedItem().getValue().getParent();
                Bible bib = (Bible) chap.getParent().getParent();
                BiblePassage passage = new BiblePassage(bib.getBibleName(), chap.getBook() + " " + chap.toString(), chap.getVerses(), false);
                QueleaApp.get().getMainWindow().getMainPanel().getSchedulePanel().getScheduleList().add(passage);
            }
        });
        setOnShown((WindowEvent event) -> {
            if (!BibleManager.get().isIndexInit()) {
                BibleManager.get().refreshAndLoad();
            }
        });
        reset();
        Scene scene = new Scene(mainPane);
        if (QueleaProperties.get().getUseDarkTheme()) {
            scene.getStylesheets().add("org/modena_dark.css");
        }
        setScene(scene);
    }

    public final void reset() {
        searchField.setText(LabelGrabber.INSTANCE.getLabel("initial.search.text"));
        searchField.focusedProperty().addListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (t1) {
                    searchField.setText("");
                    searchField.focusedProperty().removeListener(this);
                }
            }
        });
        searchField.setDisable(true);
        BibleManager.get().runOnIndexInit(() -> {
            searchField.setDisable(false);
        });
    }

    private ExecutorService updateExecutor = Executors.newSingleThreadExecutor();

    private ExecRunnable lastUpdateRunnable = null;

    private interface ExecRunnable extends Runnable {

        void cancel();
    }

    /**
     * Update the results based on the entered text.
     */
    private void update() {
        final String text = searchField.getText();
        if (text.length() > 3) {
            if (BibleManager.get().isIndexInit()) {
                searchResults.reset();
                overlay.show();
                ExecRunnable execRunnable = new ExecRunnable() {

                    private volatile boolean cancel = false;

                    public void cancel() {
                        cancel = true;
                    }

                    public void run() {
                        if (cancel) {
                            return;
                        }
                        final BibleChapter[] results = BibleManager.get().getIndex().filter(text, null);
                        Platform.runLater(() -> {
                            searchResults.reset();
                            if (!text.trim().isEmpty()) {
                                for (BibleChapter chapter : results) {
                                    if (bibles.getSelectionModel().getSelectedIndex() == 0 || chapter.getBook().getBible().getName().equals(bibles.getSelectionModel().getSelectedItem())) {
                                        for (BibleVerse verse : chapter.getVerses()) {
                                            if (verse.getText().toLowerCase().contains(text.toLowerCase())) {
                                                searchResults.add(verse);
                                            }
                                        }
                                    }
                                }
                            }
                            overlay.hide();
                            String resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.results.found");
                            if (searchResults.size() == 1 && LabelGrabber.INSTANCE.isLocallyDefined("bible.search.result.found")) {
                                resultsfoundSuffix = LabelGrabber.INSTANCE.getLabel("bible.search.result.found");
                            }
                            resultsField.setText(" " + searchResults.size() + " " + resultsfoundSuffix);
                        });
                    }
                };
                if (lastUpdateRunnable != null) {
                    lastUpdateRunnable.cancel();
                }
                lastUpdateRunnable = execRunnable;
                updateExecutor.submit(execRunnable);
            }
        }
        searchResults.reset();
        resultsField.setText(" " + LabelGrabber.INSTANCE.getLabel("bible.search.keep.typing"));
        chapterPane.getChildren().clear();
    }

    /**
     * Update the list of bibles on this search dialog.
     */


private void getPortJavaEE() throws Exception

package com.sun.ts.tests.jaxws.wsa.w2j.document.literal.delimiter;

import com.sun.ts.lib.util.*;
import com.sun.ts.lib.porting.*;
import com.sun.ts.lib.harness.*;
import jakarta.xml.soap.SOAPBody;
import jakarta.xml.soap.SOAPException;
import com.sun.ts.tests.jaxws.wsa.common.ActionNotSupportedException;
import com.sun.ts.tests.jaxws.common.*;
import java.net.URL;
import jakarta.xml.ws.*;
import jakarta.xml.soap.*;
import java.util.Properties;
import javax.xml.namespace.QName;
import com.sun.javatest.Status;
import javax.naming.InitialContext;

public class Client extends ServiceEETest {

    // The webserver defaults (overidden by harness properties)
    private static final String PROTOCOL = "http";

    private static final String HOSTNAME = "localhost";

    private static final int PORTNUM = 8000;

    // The webserver host and port property names (harness properties)
    private static final String WEBSERVERHOSTPROP = "webServerHost";

    private static final String WEBSERVERPORTPROP = "webServerPort";

    private static final String MODEPROP = "platform.mode";

    String modeProperty = null;

    private static final String PKG_NAME = "com.sun.ts.tests.jaxws.wsa.w2j.document.literal.delimiter.";

    private TSURL ctsurl = new TSURL();

    private Properties props = null;

    private String hostname = HOSTNAME;

    private int portnum = PORTNUM;

    // URL properties used by the test
    private static final String ENDPOINT_URL = "wsaw2jdldelimitertest.endpoint.1";

    private static final String WSDLLOC_URL = "wsaw2jdldelimitertest.wsdlloc.1";

    private String url = null;

    // service and port information
    private static final String NAMESPACEURI = "urn:example.com";

    private static final String SERVICE_NAME = "AddNumbersService";

    private static final String PORT_NAME = "AddNumbersPort";

    private QName SERVICE_QNAME = new QName(NAMESPACEURI, SERVICE_NAME);

    private QName PORT_QNAME = new QName(NAMESPACEURI, PORT_NAME);

    private URL wsdlurl = null;

    AddNumbersPortType port = null;

    static AddNumbersService service = null;

    private void getTestURLs() throws Exception {
        TestUtil.logMsg("Get URL's used by the test");
        String file = JAXWS_Util.getURLFromProp(ENDPOINT_URL);
        url = ctsurl.getURLString(PROTOCOL, hostname, portnum, file);
        file = JAXWS_Util.getURLFromProp(WSDLLOC_URL);
        wsdlurl = ctsurl.getURL(PROTOCOL, hostname, portnum, file);
        TestUtil.logMsg("Service Endpoint URL: " + url);
        TestUtil.logMsg("WSDL Location URL:    " + wsdlurl);
    }

    private void getPortStandalone() throws Exception {
        port = (AddNumbersPortType) JAXWS_Util.getPort(wsdlurl, SERVICE_QNAME, AddNumbersService.class, PORT_QNAME, AddNumbersPortType.class);
        TestUtil.logMsg("port=" + port);
        JAXWS_Util.setTargetEndpointAddress(port, url);
    }

{
        TestUtil.logMsg("Obtain service via WebServiceRef annotation");
        TestUtil.logMsg("service=" + service);
        port = (AddNumbersPortType) service.getAddNumbersPort();
        TestUtil.logMsg("port=" + port);
        TestUtil.logMsg("Obtained port");
        JAXWS_Util.dumpTargetEndpointAddress(port);
    }

    public static void main(String[] args) {
        Client theTests = new Client();
        Status s = theTests.run(args, System.out, System.err);
        s.exit();
    }

    /* Test setup */
    public void setup(String[] args, Properties p) throws Fault {
        props = p;
        boolean pass = true;
        try {
            hostname = p.getProperty(WEBSERVERHOSTPROP);
            if (hostname == null)
                pass = false;
            else if (hostname.equals(""))
                pass = false;
            try {
                portnum = Integer.parseInt(p.getProperty(WEBSERVERPORTPROP));
            } catch (Exception e) {
                TestUtil.printStackTrace(e);
                pass = false;
            }
            modeProperty = p.getProperty(MODEPROP);
            if (modeProperty.equals("standalone")) {
                getTestURLs();
                getPortStandalone();
            } else {
                TestUtil.logMsg("WebServiceRef is not set in Client (get it from specific vehicle)");
                service = (AddNumbersService) getSharedObject();
                getTestURLs();
                getPortJavaEE();
            }
        } catch (Exception e) {
            TestUtil.printStackTrace(e);
            throw new Fault("setup failed:", e);
        }
        if (!pass) {
            TestUtil.logErr("Please specify host & port of web server " + "in config properties: " + WEBSERVERHOSTPROP + ", " + WEBSERVERPORTPROP);
            throw new Fault("setup failed:");
        }
        logMsg("setup ok");
    }

    public void cleanup() throws Fault {
        logMsg("cleanup ok");
    }

    /*
   * @testName: testURNDefaultInputOutputActions
   *
   * @assertion_ids: WSAMD:SPEC:4004; WSAMD:SPEC:4004.1; WSAMD:SPEC:4004.2;
   *
   * @test_Strategy: Test default action pattern for WSDL input/output with URN
   * targetNamespace
   *
   */
    public void testURNDefaultInputOutputActions() throws Fault {
        TestUtil.logMsg("testURNDefaultInputOutputActions");
        boolean pass = true;
        try {
            int result = port.addNumbers(10, 10);
            if (result != 20) {
                TestUtil.logErr("result mismatch, expected 20, received " + result);
                pass = false;
            } else
                TestUtil.logMsg("result match");
        } catch (Exception e) {
            TestUtil.logErr("Caught exception: " + e.getMessage());
            TestUtil.printStackTrace(e);
            throw new Fault("testURNDefaultInputOutputActions failed", e);
        }
        if (!pass)
            throw new Fault("testURNDefaultInputOutputActions failed");
    }

    /*
   * @testName: testURNDefaultFaultAction
   *
   * @assertion_ids: WSAMD:SPEC:4004; WSAMD:SPEC:4004.3;
   *
   * @test_Strategy: Test default action pattern for WSDL fault with URN
   * targetNamespace
   *
   */
    public void testURNDefaultFaultAction() throws Fault {
        TestUtil.logMsg("testURNDefaultFaultAction");
        boolean pass = true;
        try {
            port.addNumbers(-10, 10);
            TestUtil.logErr("AddNumbersFault_Exception must be thrown");
            pass = false;
        } catch (AddNumbersFault_Exception ex) {
            TestUtil.logMsg("AddNumbersFault_Exception was thrown as expected");
        } catch (Exception e) {
            TestUtil.logErr("Caught exception: " + e.getMessage());
            TestUtil.printStackTrace(e);
            throw new Fault("testURNDefaultFaultAction failed", e);
        }
        if (!pass)
            throw new Fault("testURNDefaultAddFaultAction failed");
    }

    /*
   * @testName: testURNExplicitInputOutputActions
   *
   * @assertion_ids: WSAMD:SPEC:4004; WSAMD:SPEC:4003; WSAMD:SPEC:4003.1;
   * WSAMD:SPEC:4003.1; JAXWS:SPEC:2077; JAXWS:SPEC:2078; JAXWS:SPEC:2079;
   *
   * @test_Strategy: Test explicit association for WSDL input/output with URN
   * targetNamespace
   *
   */
    public void testURNExplicitInputOutputActions() throws Fault {
        TestUtil.logMsg("testURNExplicitInputOutputActions");
        boolean pass = true;
        try {
            int result = port.addNumbers2(10, 10);
            if (result != 20) {
                TestUtil.logErr("result mismatch, expected 20, received " + result);
                pass = false;
            } else
                TestUtil.logMsg("result match");
        } catch (Exception e) {
            TestUtil.logErr("Caught exception: " + e.getMessage());
            TestUtil.printStackTrace(e);
            throw new Fault("testURNExplicitInputOutputActions failed", e);
        }
        if (!pass)
            throw new Fault("testURNExplicitInputOutputActions failed");
    }

    /*
   * @testName: testURNExplicitFaultAction
   *
   * @assertion_ids: WSAMD:SPEC:4004; WSAMD:SPEC:4003; WSAMD:SPEC:4003.3;
   * JAXWS:SPEC:2080; JAXWS:SPEC:2081; JAXWS:SPEC:2082; JAXWS:SPEC:2083;
   *
   * @test_Strategy: Test explicit association for WSDL fault with URN
   * targetNamespace
   *
   */
    public void testURNExplicitFaultAction() throws Fault {
        TestUtil.logMsg("testURNExplicitFaultAction");
        boolean pass = true;
        try {
            int result = port.addNumbers2(-10, 10);
            TestUtil.logErr("AddNumbersFault_Exception must be thrown");
            pass = false;
        } catch (AddNumbersFault_Exception ex) {
            TestUtil.logMsg("AddNumbersFault_Exception was thrown as expected");
        } catch (Exception e) {
            TestUtil.logErr("Caught exception: " + e.getMessage());
            TestUtil.printStackTrace(e);
            throw new Fault("testURNExplicitFaultAction failed", e);
        }
        if (!pass)
            throw new Fault("testURNExplicitFaultAction failed");
    }
}