text:
"""
```
AbstractDSGEModel{T} <: AbstractModel{T}
```

The AbstractDSGEModel is defined as a subtype of AbstractModel
"""
abstract type AbstractDSGEModel{T} <: ModelConstructors.AbstractModel{T} end

function Base.show(io::IO, m::AbstractDSGEModel)
    @printf io "Dynamic Stochastic General Equilibrium Model\n"
    @printf io "no. states:             %i\n" n_states(m)
    @printf io "no. anticipated policy shocks: %i\n" n_mon_anticipated_shocks(m)
    @printf io "data vintage:           %s\n" data_vintage(m)
    @printf io "description:\n %s\n"          description(m)
end

# Retrieve model type
model_type(m::AbstractDSGEModel{T}) where T = T

# Number of anticipated policy shocks
n_anticipated_shocks(m::AbstractDSGEModel) = get_setting(m, :n_mon_anticipated_shocks)
n_anticipated_shocks_padding(m::AbstractDSGEModel) = get_setting(m, :n_mon_anticipated_shocks_padding)
n_mon_anticipated_shocks(m::AbstractDSGEModel) = get_setting(m, :n_mon_anticipated_shocks)
n_mon_anticipated_shocks_padding(m::AbstractDSGEModel) = get_setting(m, :n_mon_anticipated_shocks_padding)
n_anticipated_shocks_padding(m::AbstractDSGEModel) = get_setting(m, :n_mon_anticipated_shocks_padding)
n_z_anticipated_shocks(m::AbstractDSGEModel) = get_setting(m, :n_z_anticipated_shocks)
n_z_anticipated_shocks_padding(m::AbstractDSGEModel) = get_setting(m, :n_z_anticipated_shocks_padding)

# Dates, indices, number of periods for each regime
date_presample_start(m::AbstractDSGEModel) = get_setting(m, :date_presample_start)
date_mainsample_start(m::AbstractDSGEModel) = get_setting(m, :date_mainsample_start)
date_zlb_start(m::AbstractDSGEModel) = get_setting(m, :date_zlb_start)
date_zlb_end(m::AbstractDSGEModel) = get_setting(m, :date_zlb_end)
date_presample_end(m::AbstractDSGEModel) = Dates.lastdayofquarter(get_setting(m, :date_mainsample_start) - Dates.Month(3))
date_prezlb_end(m::AbstractDSGEModel) = Dates.lastdayofquarter(get_setting(m, :date_zlb_start) - Dates.Month(3))
date_mainsample_end(m::AbstractDSGEModel) = Dates.lastdayofquarter(get_setting(m, :date_forecast_start) - Dates.Month(3))
date_conditional_end(m::AbstractDSGEModel) = get_setting(m, :date_conditional_end)

index_presample_start(m::AbstractDSGEModel) = 1
index_mainsample_start(m::AbstractDSGEModel) = subtract_quarters(date_mainsample_start(m), date_presample_start(m)) + 1
index_zlb_start(m::AbstractDSGEModel) = subtract_quarters(date_zlb_start(m), date_presample_start(m)) + 1
index_forecast_start(m::AbstractDSGEModel) = subtract_quarters(date_forecast_start(m), date_presample_start(m)) + 1

"""
```
index_shockdec_start(m::AbstractDSGEModel)
```

Returns the index starting from which the shock decomposition is saved, where 1 is the index corresponding to date_mainsample_start(m).
"""
index_shockdec_start(m::AbstractDSGEModel) = subtract_quarters(date_shockdec_start(m), date_mainsample_start(m)) + 1

"""
```
index_shockdec_end(m::AbstractDSGEModel)
```

Returns the last index for which the shock decomposition is saved, where 1 is the index corresponding to date_mainsample_start(m).
"""
index_shockdec_end(m::AbstractDSGEModel) = subtract_quarters(date_shockdec_end(m), date_mainsample_start(m)) + 1

n_presample_periods(m::AbstractDSGEModel)   = subtract_quarters(date_mainsample_start(m), date_presample_start(m))
n_prezlb_periods(m::AbstractDSGEModel)      = subtract_quarters(date_zlb_start(m), date_mainsample_start(m))
n_zlb_periods(m::AbstractDSGEModel)         = subtract_quarters(date_forecast_start(m), date_zlb_start(m))
n_mainsample_periods(m::AbstractDSGEModel)  = subtract_quarters(date_forecast_start(m), date_mainsample_start(m))
n_conditional_periods(m::AbstractDSGEModel) = subtract_quarters(date_conditional_end(m), date_mainsample_end(m))

inds_presample_periods(m::AbstractDSGEModel)  = collect(index_presample_start(m):(index_mainsample_start(m)-1))
inds_prezlb_periods(m::AbstractDSGEModel)     = collect(index_mainsample_start(m):(index_zlb_start(m)-1))
inds_zlb_periods(m::AbstractDSGEModel)        = collect(index_zlb_start(m):(index_forecast_start(m)-1))
inds_mainsample_periods(m::AbstractDSGEModel) = collect(index_mainsample_start(m):(index_forecast_start(m)-1))

# Convenience functions for working with heterogeneous agent models
# that differentiate between backward looking "state" variables and "jump" variables
n_backward_looking_states(m::AbstractDSGEModel) = get_setting(m, :n_backward_looking_states)
n_jumps(m::AbstractDSGEModel) = get_setting(m, :n_jumps)
n_model_states(m::AbstractDSGEModel) = get_setting(m, :n_model_states)

# The numbers for n_states, and n_jumps assumes normalization
# There is a procedure in klein_solve that normalizes the state variable grids
# by removing an entry from them. Hence the number of states and jumps being
# tracked should be 1 less if normalized
# However, the number of jumps and states unnormalized are required for
# the construction of the Jacobian, hence the reason for these helpers
n_jumps_unnormalized(m::AbstractDSGEModel) = n_jumps(m) + get_setting(m, :jumps_normalization_factor)
n_backward_looking_states_unnormalized(m::AbstractDSGEModel) = n_backward_looking_states(m) + get_setting(m, :backward_looking_states_normalization_factor)
n_model_states_unnormalized(m::AbstractDSGEModel) = n_jumps_unnormalized(m) + n_backward_looking_states_unnormalized(m)
n_model_states_original(m::AbstractDSGEModel) = get_setting(m, :n_model_states_original)

"""
```
AbstractCTModel{T} <: AbstractDSGEModel{T}
```

The AbstractCTModel is defined as a subtype of AbstractDSGEModel to accomodate the
numerical methods and procedures specific to continuous time models.
"""
abstract type AbstractCTModel{T} <: AbstractDSGEModel{T} end

n_states(m::AbstractCTModel) = sum(map(i -> length(collect(m.endogenous_states)[i][2]), 1:length(keys(m.endogenous_states))))
n_shocks_expectational(m::AbstractCTModel) = sum(map(i -> length(collect(m.expected_shocks)[i][2]), 1:length(keys(m.expected_shocks))))

"""
```
AbstractHetModel{T} <: AbstractDSGEModel{T}
```

The AbstractHetModel is defined as a subtype of AbstractDSGEModel to accomodate a bunch of stuff, but for now just different impulse response functions.
"""
abstract type AbstractHetModel{T} <: AbstractDSGEModel{T} end

"""
```
AbstractRepModel{T} <: AbstractDSGEModel{T}
```

The AbstractRepresentativeModel is defined as a subtype of AbstractDSGEModel to accomodate a bunch of stuff, but for now just different impulse response functions.
"""
abstract type AbstractRepModel{T} <: AbstractDSGEModel{T} end

"""
```
get_dict(m, class, index)
```
"""
function get_dict(m::AbstractDSGEModel, class::Symbol)
    if class == :states
        m.endogenous_states
    elseif class == :obs
        m.observables
    elseif class == :pseudo
        m.pseudo_observables
    elseif class in [:shocks, :stdshocks]
        m.exogenous_shocks
    else
        throw(ArgumentError("Invalid class: $class. Must be :states, :obs, :pseudo, :shocks, or :stdshocks"))
    end
end

"""
```
get_key(m, class, index)
```
Returns the name of the state (`class = :states`), observable (`:obs`),
pseudo-observable (`:pseudo`), or shock (`:shocks` or `:stdshocks`)
corresponding to the given `index`.
"""
function get_key(m::AbstractDSGEModel, class::Symbol, index::Int)
    dict = get_dict(m, class)
    out = Base.filter(key -> dict[key] == index, collect(keys(dict)))
    if length(out) == 0
        error("Key corresponding to index $index not found for class: $class")
    elseif length(out) > 1
        error("Multiple keys corresponding to index $index found for class: $class")
    else
        return out[1]
    end
end

# Parse population mnemonic into 2 Nullable{Symbol}s from one
function parse_population_mnemonic(m::AbstractDSGEModel)
    mnemonic = get_setting(m, :population_mnemonic)
    if isnull(mnemonic)
        return [Nullable{Symbol}(), Nullable{Symbol}()]
    else
        return map(s -> Nullable(Symbol(s)), split(string(get(mnemonic)), DSGE_DATASERIES_DELIM))
    end
end

# From an augmented state space with anticipated policy shocks, get indices
# corresponding to pre-ZLB states, shocks, and observables
function inds_states_no_ant(m::AbstractDSGEModel)
    if n_mon_anticipated_shocks(m) > 0
        ind_ant1 = m.endogenous_states[:rm_tl1]
        ind_antn = m.endogenous_states[Symbol("rm_tl$(n_mon_anticipated_shocks(m))")]
        return [1:(ind_ant1-1); (ind_antn+1):n_states_augmented(m)]
    else
        return collect(1:n_states_augmented(m))
    end
end

function inds_shocks_no_ant(m::AbstractDSGEModel)
    if n_mon_anticipated_shocks(m) > 0
        ind_ant1 = m.exogenous_shocks[:rm_shl1]
        ind_antn = m.exogenous_shocks[Symbol("rm_shl$(n_mon_anticipated_shocks(m))")]
        return [1:(ind_ant1-1); (ind_antn+1):n_shocks_exogenous(m)]
    else
        return collect(1:n_shocks_exogenous(m))
    end
end

function inds_obs_no_ant(m::AbstractDSGEModel)
    if n_mon_anticipated_shocks(m) > 0
        ind_ant1 = m.observables[:obs_nominalrate1]
        ind_antn = m.observables[Symbol("obs_nominalrate$(n_mon_anticipated_shocks(m))")]
        return [1:(ind_ant1-1); (ind_antn+1):n_observables(m)]
    else
        return collect(1:n_observables(m))
    end
end

# From an augmented state space with integrated series (e.g. unit root),
# get indices corresponding to stationary states
function inds_states_no_integ_series(m::AbstractDSGEModel)
    if haskey(get_settings(m), :integrated_series)
        inds = map(i -> m.endogenous_states_augmented[i],
                   get_setting(m, :integrated_series))
        return setdiff(1:n_states_augmented(m), inds)
    else
        return collect(1:n_states_augmented(m))
    end
end

# Interface for accessing parameters
get_parameters(m::AbstractDSGEModel) = m.parameters

# Interface for accessing rng
get_rng(m::AbstractDSGEModel) = m.rng

# Interface for accessing settings dictionary
get_settings(m::AbstractDSGEModel) = hasproperty(m, :testing) ? (m.testing ? m.test_settings : m.settings) : m.settings

# Interface for accessing observables dictionary
get_observables(m::AbstractDSGEModel) = m.observables
get_pseudo_observables(m::AbstractDSGEModel) = m.pseudo_observables
get_exogenous_shocks(m::AbstractDSGEModel) = m.exogenous_shocks

# Interface for data
cond_vintage(m::AbstractDSGEModel)    = get_setting(m, :cond_vintage)
cond_id(m::AbstractDSGEModel)         = get_setting(m, :cond_id)
cond_full_names(m::AbstractDSGEModel) = get_setting(m, :cond_full_names)
cond_semi_names(m::AbstractDSGEModel) = get_setting(m, :cond_semi_names)
use_population_forecast(m::AbstractDSGEModel) = get_setting(m, :use_population_forecast)
hpfilter_population(m::AbstractDSGEModel)     = get_setting(m, :hpfilter_population)

# Interface for general computation settings
use_parallel_workers(m::AbstractDSGEModel)    = get_setting(m, :use_parallel_workers)

# Interface for estimation settings
reoptimize(m::AbstractDSGEModel)          = get_setting(m, :reoptimize)
calculate_hessian(m::AbstractDSGEModel) = get_setting(m, :calculate_hessian)
hessian_path(m::AbstractDSGEModel)      = get_setting(m, :hessian_path)
n_hessian_test_params(m::AbstractDSGEModel) = get_setting(m, :n_hessian_test_params)

# Interface for Metropolis-Hastings settings
n_mh_blocks(m::AbstractDSGEModel)       =  get_setting(m, :n_mh_blocks)
n_mh_param_blocks(m::AbstractDSGEModel) =  get_setting(m, :n_mh_param_blocks)
n_mh_simulations(m::AbstractDSGEModel)  =  get_setting(m, :n_mh_simulations)
n_mh_burn(m::AbstractDSGEModel)         =  get_setting(m, :n_mh_burn)
mh_thin(m::AbstractDSGEModel)           =  get_setting(m, :mh_thin)

# Interface for forecast settings
date_forecast_start(m::AbstractDSGEModel)   = get_setting(m, :date_forecast_start)
forecast_block_size(m::AbstractDSGEModel)   = get_setting(m, :forecast_block_size)
forecast_start_block(m::AbstractDSGEModel)  = get_setting(m, :forecast_start_block)
forecast_input_file_overrides(m::AbstractDSGEModel) = get_setting(m, :forecast_input_file_overrides)
forecast_uncertainty_override(m::AbstractDSGEModel) = get_setting(m, :forecast_uncertainty_override)
forecast_smoother(m::AbstractDSGEModel)     = get_setting(m, :forecast_smoother)
forecast_tdist_df_val(m::AbstractDSGEModel) = get_setting(m, :forecast_tdist_df_val)
forecast_tdist_shocks(m::AbstractDSGEModel) = get_setting(m, :forecast_tdist_shocks)
forecast_zlb_value(m::AbstractDSGEModel)    = get_setting(m, :forecast_zlb_value)
impulse_response_horizons(m::AbstractDSGEModel) = get_setting(m, :impulse_response_horizons)
n_shockdec_periods(m::AbstractDSGEModel)    = index_shockdec_end(m) - index_shockdec_start(m) + 1

# Function for getting the alternative policy. Note that, in the case of imperfect awareness,
# i.e. when uncertain_altpolicy is true, this function will return the policy that is actually implemented,
# instead of other potential alternative policies which households believe could occur.
#
# Furthermore, do NOT delete the backup cases when regime_eqcond_info is not defined, namely
# the check for whether :alternative_policy is a Setting. This last check is necessary for
# the scenarios code to continue working.
#
# Finally, the check for :regime_eqcond_info MUST come first, or else the regime-switching code
# will not work as intended, namely that :regime_eqcond_info specifies equilibrium conditions
# which differ from the default ones and thus should determine the "final" permanent policy
# that is believed to hold until "the end of time" (i.e. forever since it is an infinite horizon model).
alternative_policy(m::AbstractDSGEModel) = haskey(get_settings(m), :regime_eqcond_info) && # no check for n_regimes b/c if it is not there, then
    haskey(get_setting(m, :regime_eqcond_info), get_setting(m, :n_regimes)) ?              # it is better to throw an error since regime_eqcond_info
    get_setting(m, :regime_eqcond_info)[get_setting(m, :n_regimes)].alternative_policy :   # will not work in general anyway.
    (haskey(get_settings(m), :alternative_policy) ? get_setting(m, :alternative_policy) : AltPolicy(:historical, eqcond, solve))

# Some additional date settings related to forecasts
function date_forecast_end(m::AbstractDSGEModel)
    if haskey(get_settings(m), :date_forecast_end)
        return get_setting(m, :date_forecast_end)
    else
        date = date_forecast_start(m) + Dates.Month(3 * (forecast_horizons(m)-1))
        return Dates.lastdayofquarter(date)
    end
end

function forecast_horizons(m::AbstractDSGEModel; cond_type::Symbol = :none)
    horizons = get_setting(m, :forecast_horizons)
    if cond_type == :none
        return horizons
    else
        return horizons - n_conditional_periods(m)
    end
end

function date_shockdec_start(m::AbstractDSGEModel)
    startdate = get_setting(m, :shockdec_startdate)
    if (Nullables.isnull(startdate)) | (startdate===nothing)
        return DSGE.date_mainsample_start(m)
    else
        return get(startdate)
    end
end

function date_shockdec_end(m::AbstractDSGEModel)
    enddate =  get_setting(m, :shockdec_enddate)
    if !isnull(enddate)
        return get(enddate)
    else
        return date_forecast_end(m)
    end
end

"""
```
load_parameters_from_file(m::AbstractDSGEModel,path::String)
```
Returns a vector of parameters, read from a file, suitable for updating `m`.
"""
function load_parameters_from_file(m::AbstractDSGEModel, path::String)

    if isfile(path) && splitext(path)[2] == ".h5"
        x  = h5open(path, "r") do file
            try
                read(file, "params")
            catch
                error("$path does not contain variable params")
            end
        end
    else
        error("$path is not a valid HDF5 file.")
    end

    if m.spec=="smets_wouters" && length(x)==42
        x = vcat(x, zeros(7))
    end

    @assert length(x) == length(m.parameters)
    @assert eltype(x) == typeof(m.parameters[1].value)
    return x
end

"""
```
specify_mode!(m::AbstractDSGEModel, mode_file::String=""; verbose=:low)
```

Updates the values of `m.parameters` with the values from
`mode_file`. Sets `reoptimize` setting to `false`.

Usage: should be run before calling `estimate(m)`, e.g.:

    m = Model990()
    specify_mode!(m, modefile)
    estimate(m)
"""
function specify_mode!(m::AbstractDSGEModel, mode_file::String = ""; verbose=:low)

    m <= Setting(:reoptimize, false)

    if mode_file == ""
        mode_file = inpath(m, "user", "paramsmode.h5")
    end
    mode_file = normpath(mode_file)

    DSGE.update!(m,load_parameters_from_file(m,mode_file))

    println(verbose, :low, "Loaded previous mode from $mode_file.")
end

"""
```
specify_hessian!(m::AbstractDSGEModel, path::String=""; verbose=:low)
```

Specify a Hessian matrix calculated at the posterior mode to use in the model estimation. If
no path is provided, will attempt to detect location.
"""
function specify_hessian!(m::AbstractDSGEModel, path::String=""; verbose=:low)
    if isempty(path)
        path = inpath(m, "user", "hessian.h5")
    end

    if isfile(path) && splitext(path)[2] == ".h5"
        m <= Setting(:hessian_path, normpath(abspath(path)))
    else
        error("Invalid input Hessian file: $path",)
    end

    m <= Setting(:calculate_hessian, false)

    println(verbose, :low, "Specified hessian from $path.")
end

"""
```
transform_to_model_space!(m::AbstractDSGEModel, values::Vector{T}; regime_switching::Bool = false) where T<:AbstractFloat
```

Transforms `values` from the real line to the model space, and assigns `values[i]` to
`m.parameters[i].value` for non-steady-state parameters. Recomputes the steady-state
parameter values.

### Arguments
- `m`: the model object
- `values`: the new values to assign to non-steady-state parameters.
- `regime_switching`: set to true if the model's parameters are regime-switching
"""
function transform_to_model_space!(m::AbstractDSGEModel, values::Vector{T};
                                   regime_switching::Bool = false) where {T<:AbstractFloat}
    new_values = transform_to_model_space(m.parameters, values; regime_switching = regime_switching)
    DSGE.update!(m, new_values)
    steadystate!(m)
end

"""
```
update!(m::AbstractDSGEModel, values::Vector{T}) where T<:AbstractFloat
```

Update `m.parameters` with `values`, recomputing the steady-state parameter values.

### Arguments:
- `m`: the model object
- `values`: the new values to assign to non-steady-state parameters.
"""
function update!(m::AbstractDSGEModel, values::AbstractVector{T}) where {T <: Real}
    ModelConstructors.update!(m.parameters, values)
    steadystate!(m)
end

"""
```
update!(m::AbstractDSGEModel, values::ParameterVector{T};
    regime_switching::Bool = false, toggle::Bool = true) where T
```
Update `m.parameters` with `values`, recomputing the steady-state parameter values.

### Arguments
- `m`: the model object
- `values`: the new values to assign to non-steady-state parameters.

### Keyword
- `regime_switching`: if true, then we assume the parameters are regime-switching,
    in which case `update!` assumes the `value` field
    of each parameter in values` holds the parameter value in the first regime, and
    then we update the field `regimes` for each parameter
- `toggle`: if true, we call `ModelConstructors.toggle_regime!(values)` before
    updating any values to ensure the `value` field of the parameters in `values`
    correspond to regime 1 values.
"""
function update!(m::AbstractDSGEModel, values::ParameterVector{T};
                 regime_switching::Bool = false, toggle::Bool = true) where {T <: Real}

    # Update regime-switching if length of `values` exceeds m.parameters
    if regime_switching
        if toggle
            ModelConstructors.toggle_regime!(values, 1)
        end

        # Update first-regime values
        ModelConstructors.update!(m.parameters, [θ.value for θ in values])

        # Update remaining regimes
        for (i, para) in enumerate(m.parameters)
            if !isempty(para.regimes)
                for (ind, val) in para.regimes[:value]
                    if ind == 1
                        ModelConstructors.set_regime_val!(para, 1, para.value)
                    else
                        ModelConstructors.set_regime_val!(para, ind, regime_val(values[i], ind))
                    end
                end
            end
        end
    else
        ModelConstructors.update!(m.parameters, [θ.value for θ in values])
    end

    steadystate!(m)
end

"""
```
mutable struct ShockGroup
```

The `ShockGroup` mutable struct is used in `prepare_means_table_shockdec` and
`plot_shock_decompositions`. When plotting shock decompositions, we usually want
to group the shocks into categories (financial, monetary policy, etc.) so that
the resulting grouped bar plot is legible.

### Fields

- `name::String`
- `shocks::Vector{Symbol}`
- `color::Colorant`
"""
mutable struct ShockGroup
    name::String
    shocks::Vector{Symbol}
    color::Colorant
end

function ShockGroup(name::String, shocks::Vector{Symbol}, color_name::Symbol)
    color = parse(Colorant, color_name)
    return ShockGroup(name, shocks, color)
end

mutable struct SteadyStateConvergenceError <: Exception
    msg::String
end
SteadyStateConvergenceError() = SteadyStateConvergenceError("SteadyState didn't converge")
Base.showerror(io::IO, ex::SteadyStateConvergenceError) = print(io, ex.msg)

"""
```
setup_regime_switching_inds!(m::AbstractDSGEModel; cond_type::Symbol = :none)
```

calculates the indices needed to solve and forecast a model with regime-switching.

### Keywords
- `cond_type`: the correct regime indices for forecasting depend on whether the forecast is conditional or not
"""
function setup_regime_switching_inds!(m::AbstractDSGEModel; cond_type::Symbol = :none)

    if haskey(get_settings(m), :regime_switching) ? !get_setting(m, :regime_switching) : true
        @warn "The setting :regime_switching is either false or is not defined yet. Updating the setting to be true."
        m <= Setting(:regime_switching, true)
    end

    n_hist_regimes = 0
    n_cond_regimes = 0
    n_regimes = length(get_setting(m, :regime_dates))
    post_cond_end = iterate_quarters(date_conditional_end(m), 1) # Period after conditional forecasting ends
    set_reg_forecast_start   = false # These flags are needed to tell whether or not we actually set these regimes.
    set_post_conditional_end = false # W/out these flags, if m already has reg_forecast_start, then it won't be properly set
    reg_forecast_start_str = "Regime in which the forecast starts."
    reg_post_conditional_end_str = "Regime one period after the conditional forecast ends."
    for (key, val) in get_setting(m, :regime_dates)
        if val == date_forecast_start(m)
            m <= Setting(:reg_forecast_start, key, reg_forecast_start_str)
            set_reg_forecast_start = true
        end
        if val == post_cond_end
            m <= Setting(:reg_post_conditional_end, key, reg_post_conditional_end_str)
            set_post_conditional_end = true
        end
        if val < date_forecast_start(m)
            n_hist_regimes += 1
        end
        if date_forecast_start(m) <= val <= date_conditional_end(m)
            n_cond_regimes += 1
        end
    end
    if !set_reg_forecast_start
        # Then the forecast begins in the middle of a regime
        m <= Setting(:reg_forecast_start, findlast(sort!(collect(values(get_setting(m, :regime_dates)))) .< date_forecast_start(m)),
                     reg_forecast_start_str)
    end
    if !set_post_conditional_end
        # Then the conditional forecast ends in the middle of a regime
        m <= Setting(:reg_post_conditional_end,
                     findlast(sort!(collect(values(get_setting(m, :regime_dates)))) .<= date_conditional_end(m)),
                     reg_post_conditional_end_str) # or .< post_cond_end
    end

    # Infer number of regimes in the forecast horizon from reg_forecast_start
    n_fcast_regimes = n_regimes - get_setting(m, :reg_forecast_start) + 1

    m <= Setting(:n_regimes, n_regimes, "Total number of regimes")
    m <= Setting(:n_hist_regimes, n_hist_regimes, "Number of regimes in the history")
    m <= Setting(:n_fcast_regimes, n_fcast_regimes, "Number of regimes in the forecast horizon")
    m <= Setting(:n_cond_regimes, n_cond_regimes, "Number of regime switches during the conditional forecast horizon")

    return m
end

# Dummy function for eqcond, relevant when using gensys2
function eqcond(m::AbstractDSGEModel, Γ0::AbstractMatrix{S}, Γ1::AbstractMatrix{S},
                C::AbstractVector{S}, Ψ::AbstractMatrix{S}, Π::AbstractMatrix{S}) where {S <: Real}
    return Γ0, Γ1, C, Ψ, Π
end

"""
```
setup_param_regimes!(m::AbstractDSGEModel, param_regs::Matrix{Int} = []

Function to set up the model with parameter regime switching
for estimation. param_regs should be a matrix where for each row r,
the i{th} element is the parameter regime for the i{th} model regime
for parameter r (including parameters with no regime-switching: set
the rows for non-regime-switching parameters to all 1s, although any
value will give the same result).
```
"""
function setup_param_regimes!(m::AbstractDSGEModel, param_mat::Array{Int, 2} = Matrix{Int}(undef, 0, 0))

    param_reg   = Dict{Symbol, Dict{Int, Int}}()
    nmodel_regs = haskey(get_settings(m), :n_regimes) ? get_setting(m, :n_regimes) : 1

    if isempty(param_mat)
        param_mat = ones(n_parameters(m), nmodel_regs)
    end

    @assert nmodel_regs == size(param_mat, 2) "The number of columns in `param_mat` must match the number of model regimes"

    for i in 1:n_parameters(m)
        reg_dict = Dict{Int, Int}()
        for reg in 1:nmodel_regs
            reg_dict[reg] = param_mat[i, reg]
        end
        param_reg[m.parameters[i].key] = reg_dict
    end

    m <= Setting(:model2para_regime, param_reg)

    return m
end


text:
using System;

namespace Gherkin.Ast
{
    [Serializable]
    public class Location
    {
        public int Line { get; private set; }
        public int Column { get; private set; }

        public Location(int line = 0, int column = 0)
        {
            Line = line;
            Column = column;
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
CREATE TABLE [dbo].[winter_Routes] (
    [DataSetId]                 NVARCHAR (255) DEFAULT ('') NOT NULL,
    [Routes_Description_id]     NVARCHAR (255) DEFAULT ('') NOT NULL,
    [Routes_Description]        NVARCHAR (255) DEFAULT ('') NOT NULL,
    [Routes_RouteSectionRef_id] NVARCHAR (255) DEFAULT ('') NOT NULL,
    [Routes_RouteSectionRef]    NVARCHAR (255) DEFAULT ('') NOT NULL,
    CONSTRAINT [winterpk_routes] PRIMARY KEY CLUSTERED ([Routes_RouteSectionRef] ASC, [DataSetId] ASC)
);

GO
CREATE UNIQUE NONCLUSTERED INDEX [winterix_routes_routedescriptionid]
    ON [dbo].[winter_Routes]([Routes_Description_id] ASC, [DataSetId] ASC);


text:
require 'pender_store'

module MediaVideoArchiver
  extend ActiveSupport::Concern

  included do
    Media.declare_archiver('video', [/^.*$/], :only)
  end

  def archive_to_video
    self.class.archive_video_in_background(self.original_url, ApiKey.current&.id)
  end

  module ClassMethods
    def archive_video_in_background(url, key_id)
      ArchiverWorker.perform_async(url, :video_archiver, key_id)
    end

    def send_to_video_archiver(url, key_id, supported = nil)
      handle_archiving_exceptions('video_archiver', { url: url, key_id: key_id }) do
        supported = supported_video?(url, key_id) if supported.nil?
        return if supported.is_a?(FalseClass) || notify_video_already_archived(url, key_id)
        id = Media.get_id(url)
        local_folder = File.join(Rails.root, 'tmp', 'videos', id)
        uri = URI.encode(url)
        proxy = "--proxy=#{Media.yt_download_proxy(uri)}"
        output = "-o#{local_folder}/#{id}.%(ext)s"
        system('youtube-dl', uri, proxy, output, '--restrict-filenames', '--no-warnings', '-q', '--write-all-thumbnails', '--write-info-json', '--all-subs', '-fogg/mp4/webm')

        if $?.success?
          Media.store_video_folder(url, local_folder, self.archiving_folder, key_id)
        else
          raise Pender::RetryLater, "(#{$?.exitstatus}) Requested video not available for download"
        end
      end
    end

    def archiving_folder
      Pender::Store.current.storage_path('video')
    end

    def notify_video_already_archived(url, key_id)
      id = Media.get_id(url)
      data = Pender::Store.current.read(id, :json)
      return if data.nil? || data.dig(:archives, :video_archiver, :location).nil?
      settings = Media.api_key_settings(key_id)
      Media.notify_webhook('video_archiver', url, data, settings)
    end

    def supported_video?(url, key_id = nil)
      uri = URI.encode url
      system('youtube-dl', uri, "--proxy=#{Media.yt_download_proxy(uri)}", '--restrict-filenames', '--no-warnings', '-g', '-q')
      unless $?.success?
        data = { error: { message: "#{$?.exitstatus} Unsupported URL", code: LapisConstants::ErrorCodes::const_get('ARCHIVER_NOT_SUPPORTED_MEDIA') }}
        Media.notify_webhook_and_update_cache('video_archiver', url, data, key_id)
      end
      $?.success?
    end

    def yt_download_proxy(url)
      uri = URI.parse(url)
      return unless uri.host.match(/youtube\.com/)
      proxy = RequestHelper.valid_proxy('ytdl_proxy')
      return nil unless proxy
      "http://#{proxy.dig('user_prefix')}:#{proxy.dig('pass')}@#{proxy.dig('host')}:#{proxy.dig('port')}"
    end

    def store_video_folder(url, local_path, public_path, key_id)
      Pender::Store.current.upload_video_folder(local_path)
      id = File.basename(local_path)
      public_path = File.join(public_path, id)
      data = organize_video_files(public_path, local_path)
      FileUtils.rm_rf(local_path)
      Media.notify_webhook_and_update_cache('video_archiver', url, data, key_id)
    end

    def organize_video_files(public_path, local_path)
      data = { info: nil, videos: [], subtitles: [], thumbnails: [] }
      Dir.glob("#{local_path}/*").each do |filename|
        filepath = "#{public_path}/#{File.basename(filename)}"
        mime_type = Rack::Mime.mime_type(File.extname(filename))
        case mime_type
        when /^image/
          data[:thumbnails] << filepath
        when /^video/
          data[:videos] << filepath
          data[:location] ||= filepath
        when /application\/json/
          data[:info] ||= filepath
        else
          data[:subtitles] << filepath
        end
      end
      data
    end
  end
end


text:
namespace Efrpg
{
    public abstract class EntityName
    {
        public string DbName;        // Raw name as obtained from the database
        public string NameHumanCase; // Name adjusted for C# generator output
    }
}


text:
XTRACE=$(set +o | grep xtrace)
set +o xtrace

LIBDIR=$DEST/designate/devstack/lib

source $LIBDIR/wsgi

# Get backend configuration
# -------------------------
if is_service_enabled designate && [[ -r $DESIGNATE_PLUGINS/backend-$DESIGNATE_BACKEND_DRIVER ]]; then
    # Load plugin
    source $DESIGNATE_PLUGINS/backend-$DESIGNATE_BACKEND_DRIVER
fi

# DevStack Plugin
# ---------------

# cleanup_designate - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_designate {
    sudo rm -rf $DESIGNATE_STATE_PATH
    sudo rm -f $(apache_site_config_for designate-api)
    remove_uwsgi_config "$DESIGNATE_UWSGI_CONF" "$DESIGNATE_UWSGI"
    cleanup_designate_backend
}

# configure_designate - Set config files, create data dirs, etc
function configure_designate {
    [ ! -d $DESIGNATE_CONF_DIR ] && sudo mkdir -m 755 -p $DESIGNATE_CONF_DIR
    sudo chown $STACK_USER $DESIGNATE_CONF_DIR

    [ ! -d $DESIGNATE_LOG_DIR ] &&  sudo mkdir -m 755 -p $DESIGNATE_LOG_DIR
    sudo chown $STACK_USER $DESIGNATE_LOG_DIR

    # (Re)create ``designate.conf``
    rm -f $DESIGNATE_CONF

    # General Configuration
    iniset_rpc_backend designate $DESIGNATE_CONF DEFAULT

    iniset $DESIGNATE_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
    iniset $DESIGNATE_CONF DEFAULT state_path $DESIGNATE_STATE_PATH
    iniset $DESIGNATE_CONF DEFAULT root-helper sudo designate-rootwrap $DESIGNATE_ROOTWRAP_CONF
    iniset $DESIGNATE_CONF storage:sqlalchemy connection `database_connection_url designate`

    # Quota Configuration
    iniset $DESIGNATE_CONF DEFAULT quota_zones $DESIGNATE_QUOTA_ZONES
    iniset $DESIGNATE_CONF DEFAULT quota_zone_recordsets $DESIGNATE_QUOTA_ZONE_RECORDSETS
    iniset $DESIGNATE_CONF DEFAULT quota_zone_records $DESIGNATE_QUOTA_ZONE_RECORDS
    iniset $DESIGNATE_CONF DEFAULT quota_recordset_records $DESIGNATE_QUOTA_RECORDSET_RECORDS
    iniset $DESIGNATE_CONF DEFAULT quota_api_export_size $DESIGNATE_QUOTA_API_EXPORT_SIZE

    # Coordination Configuration
    if [[ -n "$DESIGNATE_COORDINATION_URL" ]]; then
        iniset $DESIGNATE_CONF coordination backend_url $DESIGNATE_COORDINATION_URL
    fi

    # Agent Configuration
    iniset $DESIGNATE_CONF service:agent workers $API_WORKERS

    # API Configuration
    sudo cp $DESIGNATE_DIR/etc/designate/api-paste.ini $DESIGNATE_APIPASTE_CONF
    iniset $DESIGNATE_CONF service:api enabled_extensions_v2 $DESIGNATE_ENABLED_EXTENSIONS_V2
    iniset $DESIGNATE_CONF service:api enabled_extensions_admin $DESIGNATE_ENABLED_EXTENSIONS_ADMIN
    iniset $DESIGNATE_CONF service:api enable_host_header True
    iniset $DESIGNATE_CONF service:api enable_api_v2 $DESIGNATE_ENABLE_API_V2
    iniset $DESIGNATE_CONF service:api enable_api_admin $DESIGNATE_ENABLE_API_ADMIN

    # Central Configuration
    iniset $DESIGNATE_CONF service:central workers $API_WORKERS

    # mDNS Configuration
    iniset $DESIGNATE_CONF service:mdns listen ${DESIGNATE_SERVICE_HOST}:${DESIGNATE_SERVICE_PORT_MDNS}
    iniset $DESIGNATE_CONF service:mdns workers $API_WORKERS

    # Producer Configuration
    iniset $DESIGNATE_CONF service:producer workers $API_WORKERS

    # Sink Configuration
    iniset $DESIGNATE_CONF service:sink workers $API_WORKERS

    # Worker Configuration
    iniset $DESIGNATE_CONF service:worker poll_max_retries $DESIGNATE_POLL_RETRIES
    iniset $DESIGNATE_CONF service:worker poll_retry_interval $DESIGNATE_POLL_INTERVAL
    iniset $DESIGNATE_CONF service:worker workers $API_WORKERS

    # Set up Notifications/Ceilometer Integration
    iniset $DESIGNATE_CONF oslo_messaging_notifications driver "$DESIGNATE_NOTIFICATION_DRIVER"
    iniset $DESIGNATE_CONF oslo_messaging_notifications topics "$DESIGNATE_NOTIFICATION_TOPICS"

    # Root Wrap
    sudo cp $DESIGNATE_DIR/etc/designate/rootwrap.conf.sample $DESIGNATE_ROOTWRAP_CONF
    iniset $DESIGNATE_ROOTWRAP_CONF DEFAULT filters_path $DESIGNATE_DIR/etc/designate/rootwrap.d root-helper

    # Oslo Concurrency
    iniset $DESIGNATE_CONF oslo_concurrency lock_path "$DESIGNATE_STATE_PATH"

    # Set up the rootwrap sudoers for designate
    local rootwrap_sudoer_cmd="$DESIGNATE_BIN_DIR/designate-rootwrap $DESIGNATE_ROOTWRAP_CONF *"
    local tempfile=`mktemp`
    echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_sudoer_cmd" >$tempfile
    chmod 0440 $tempfile
    sudo chown root:root $tempfile
    sudo mv $tempfile /etc/sudoers.d/designate-rootwrap

    if is_service_enabled tls-proxy; then
        iniset $DESIGNATE_CONF keystone cafile $SSL_BUNDLE_FILE
    fi

    # Setup the Keystone Integration
    if is_service_enabled keystone; then
        iniset $DESIGNATE_CONF service:api auth_strategy keystone
        configure_keystone_authtoken_middleware $DESIGNATE_CONF designate
        iniset $DESIGNATE_CONF keystone region_name $REGION_NAME
        iniset $DESIGNATE_CONF service:api quotas_verify_project_id True
    fi

    # Logging Configuration
    setup_systemd_logging $DESIGNATE_CONF

    # Backend Plugin Configuation
    configure_designate_backend

    if [[ "$DESIGNATE_WSGI_MODE" == "uwsgi" ]]; then
        designate_configure_uwsgi
    else
        designate_configure_mod_wsgi
    fi
}

function configure_designatedashboard {
    # Compile message catalogs
    if [ -d ${DESIGNATEDASHBOARD_DIR}/designatedashboard/locale ]; then
        (cd ${DESIGNATEDASHBOARD_DIR}/designatedashboard; DJANGO_SETTINGS_MODULE=openstack_dashboard.settings ../manage.py compilemessages)
    fi
}

# Configure the needed tempest options
function configure_designate_tempest() {
    if is_service_enabled tempest; then
        # Tell tempest we're available
        iniset $TEMPEST_CONFIG service_available designate True

        # Tell tempest which APIs are available
        iniset $TEMPEST_CONFIG dns_feature_enabled api_v2 $DESIGNATE_ENABLE_API_V2
        iniset $TEMPEST_CONFIG dns_feature_enabled api_admin $DESIGNATE_ENABLE_API_ADMIN
        iniset $TEMPEST_CONFIG dns_feature_enabled api_v2_root_recordsets True
        iniset $TEMPEST_CONFIG dns_feature_enabled api_v2_quotas True
        iniset $TEMPEST_CONFIG dns_feature_enabled api_v2_quotas_verify_project True
        iniset $TEMPEST_CONFIG dns_feature_enabled bug_1573141_fixed True
        iniset $TEMPEST_CONFIG dns_feature_enabled bug_1932026_fixed True

        # Tell tempest where are nameservers are.
        nameservers=$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_DNS
        # TODO(kiall): Remove hardcoded list of plugins
        case $DESIGNATE_BACKEND_DRIVER in
            bind9)
                nameservers="$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_DNS"
                ;;
            dynect)
                nameservers="$DESIGNATE_DYNECT_NAMESERVERS"
                ;;
        esac

        if [ ! -z "$DESIGNATE_NAMESERVERS" ]; then
            nameservers=$DESIGNATE_NAMESERVERS
        fi

        iniset $TEMPEST_CONFIG dns nameservers $nameservers

        # For legacy functionaltests
        iniset $TEMPEST_CONFIG designate nameservers $nameservers
    fi
}

# create_designate_accounts - Set up common required designate accounts

# Tenant               User       Roles
# ------------------------------------------------------------------
# service              designate  admin        # if enabled
function create_designate_accounts {
    if is_service_enabled designate-api; then
        create_service_user "designate"

        local designate_api_url="$DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST/dns"

        get_or_create_service "designate" "dns" "Designate DNS Service"
        get_or_create_endpoint \
            "dns" \
            "$REGION_NAME" \
            "$designate_api_url"
    fi
}

# create_designate_pool_configuration - Create Pool Configuration
function create_designate_pool_configuration {
    # Sync Pools Config
    $DESIGNATE_BIN_DIR/designate-manage pool update --file $DESIGNATE_CONF_DIR/pools.yaml

    # Allow Backends to do backend specific tasks
    if function_exists create_designate_pool_configuration_backend; then
        create_designate_pool_configuration_backend
    fi
}

# init_designate - Initialize etc.
function init_designate {
    # (Re)create designate database
    recreate_database designate utf8

    # Init and migrate designate database
    $DESIGNATE_BIN_DIR/designate-manage database sync

    init_designate_backend
}

# install_designate - Collect source and prepare
function install_designate {
    if [[ "$DESIGNATE_WSGI_MODE" == "uwsgi" ]]; then
        install_apache_uwsgi
    else
        install_apache_wsgi
    fi

    if is_fedora; then
        # bind-utils package provides `dig`
        install_package bind-utils
    fi

    git_clone $DESIGNATE_REPO $DESIGNATE_DIR $DESIGNATE_BRANCH
    setup_develop $DESIGNATE_DIR

    # Install reqs for tooz driver
    if [[ "$DESIGNATE_COORDINATION_URL" =~ "memcached" ]]; then
        pip_install_gr "pymemcache"
    fi

    install_designate_backend
}

# install_designateclient - Collect source and prepare
function install_designateclient {
    if use_library_from_git "python-designateclient"; then
        git_clone_by_name "python-designateclient"
        setup_dev_lib "python-designateclient"
    else
        pip_install_gr "python-designateclient"
    fi
}

# install_designatedashboard - Collect source and prepare
function install_designatedashboard {
    git_clone_by_name "designate-dashboard"
    setup_dev_lib "designate-dashboard"

    for panel in _1710_project_dns_panel_group.py \
                 _1721_dns_zones_panel.py \
                 _1722_dns_reversedns_panel.py; do
        ln -fs $DESIGNATEDASHBOARD_DIR/designatedashboard/enabled/$panel $HORIZON_DIR/openstack_dashboard/local/enabled/$panel
    done
}

# install_designatetempest - Collect source and prepare
function install_designatetempest {
    git_clone_by_name "designate-tempest-plugin"
    setup_dev_lib "designate-tempest-plugin"
}

# start_designate - Start running processes
function start_designate {
    start_designate_backend

    run_process designate-central "$DESIGNATE_BIN_DIR/designate-central --config-file $DESIGNATE_CONF"
    run_process designate-mdns "$DESIGNATE_BIN_DIR/designate-mdns --config-file $DESIGNATE_CONF"
    run_process designate-agent "$DESIGNATE_BIN_DIR/designate-agent --config-file $DESIGNATE_CONF"
    run_process designate-sink "$DESIGNATE_BIN_DIR/designate-sink --config-file $DESIGNATE_CONF"

    run_process designate-worker "$DESIGNATE_BIN_DIR/designate-worker --config-file $DESIGNATE_CONF"
    run_process designate-producer "$DESIGNATE_BIN_DIR/designate-producer --config-file $DESIGNATE_CONF"

    if [[ "$DESIGNATE_WSGI_MODE" == "uwsgi" ]]; then
        run_process "designate-api" "$(which uwsgi) --procname-prefix designate-api --ini $DESIGNATE_UWSGI_CONF"
        enable_apache_site designate-api-wsgi
        restart_apache_server
    else
        enable_apache_site designate-api
        restart_apache_server
    fi

    echo "Waiting for designate-api to start..."
    if ! wait_for_service $SERVICE_TIMEOUT $DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST/dns; then
        die $LINENO "designate-api did not start"
    fi
}

# stop_designate - Stop running processes
function stop_designate {
    if [[ "$DESIGNATE_WSGI_MODE" == "uwsgi" ]]; then
        stop_process "designate-api"
        disable_apache_site designate-api-wsgi
        restart_apache_server
    else
        disable_apache_site designate-api
        restart_apache_server
    fi

    stop_process designate-central
    stop_process designate-mdns
    stop_process designate-agent
    stop_process designate-sink
    stop_process designate-worker
    stop_process designate-producer

    stop_designate_backend
}

# This is the main for plugin.sh
if is_service_enabled designate; then
    # Sanify check for agent backend
    # ------------------------------
    if ! is_service_enabled designate-agent && [ "$DESIGNATE_BACKEND_DRIVER" == "agent" ]; then
        die $LINENO "To use the agent backend, you must enable the designate-agent service"
    fi

    if [[ "$1" == "stack" && "$2" == "install" ]]; then
        echo_summary "Installing Designate client"
        install_designateclient

        echo_summary "Installing Designate"
        stack_install_service designate

        if is_service_enabled horizon; then
            echo_summary "Installing Designate dashboard"
            install_designatedashboard
        fi

        if is_service_enabled tempest; then
            echo_summary "Installing Designate Tempest Plugin"
            install_designatetempest
        fi

    elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
        echo_summary "Configuring Designate"
        configure_designate
        if is_service_enabled horizon; then
            echo_summary "Configuring Designate dashboard"
            configure_designatedashboard
        fi

        if is_service_enabled keystone; then
            echo_summary "Creating Designate Keystone accounts"
            create_designate_accounts
        fi

    elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
        echo_summary "Initializing Designate"
        init_designate

        echo_summary "Starting Designate"
        start_designate

        echo_summary "Creating Pool Configuration"
        create_designate_pool_configuration
    elif [[ "$1" == "stack" && "$2" == "test-config" ]]; then
        echo_summary "Configuring Tempest options for Designate"
        configure_designate_tempest
    fi

    if [[ "$1" == "unstack" ]]; then
        stop_designate
    fi

    if [[ "$1" == "clean" ]]; then
        echo_summary "Cleaning Designate"
        cleanup_designate
    fi
fi

# Restore xtrace
$XTRACE


text:
package de.philipphager.disclosure.feature.app.detail.tutorials;

import android.net.Uri;
import android.text.Spanned;
import de.philipphager.disclosure.feature.navigation.Navigates;

public interface EditPermissionsTutorialView extends Navigates {
  void setDescription(Spanned description);

  void showVideo(Uri videoUri);
}


text:
package org.apache.mina.filter.ssl;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.filterchain.IoFilter.NextFilter;
import org.apache.mina.core.filterchain.IoFilterEvent;
import org.apache.mina.core.future.DefaultWriteFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoEventType;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.write.DefaultWriteRequest;
import org.apache.mina.core.write.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A helper class using the SSLEngine API to decrypt/encrypt data.
 *

 * Each connection has a SSLEngine that is used through the lifetime of the connection.
 * We allocate buffers for use as the outbound and inbound network buffers.
 * These buffers handle all of the intermediary data for the SSL connection. To make things easy,
 * we'll require outNetBuffer be completely flushed before trying to wrap any more data.
 *

 * This class is not to be used by any client, it's closely associated with the SSL Filter.
 * None of its methods are public as they should not be used by any other class but from
 * the SslFilter class, in the same package
 *
 * @author Apache MINA Project
 */
/** No qualifier*/
class SslHandler {
    /** A logger for this class */
    private final static Logger LOGGER = LoggerFactory.getLogger(SslHandler.class);

    /** The SSL Filter which has created this handler */
    private final SslFilter sslFilter;

    /** The current session */
    private final IoSession session;

    private final Queue<IoFilterEvent> preHandshakeEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();

    private final Queue<IoFilterEvent> filterWriteEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();

    /** A queue used to stack all the incoming data until the SSL session is established */
    private final Queue<IoFilterEvent> messageReceivedEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();

    private SSLEngine sslEngine;

    /**
     * Encrypted data from the net
     */
    private IoBuffer inNetBuffer;

    /**
     * Encrypted data to be written to the net
     */
    private IoBuffer outNetBuffer;

    /**
     * Application cleartext data to be read by application
     */
    private IoBuffer appBuffer;

    /**
     * Empty buffer used during initial handshake and close operations
     */
    private final IoBuffer emptyBuffer = IoBuffer.allocate(0);

    private SSLEngineResult.HandshakeStatus handshakeStatus;

    /**
     * A flag set to true when the first SSL handshake has been completed
     * This is used to avoid sending a notification to the application handler
     * when we switch to a SECURE or UNSECURE session.
     */
    private boolean firstSSLNegociation;

    /** A flag set to true when a SSL Handshake has been completed */
    private boolean handshakeComplete;

    /** A flag used to indicate to the SslFilter that the buffer
     * it will write is already encrypted (this will be the case
     * for data being produced during the handshake). */
    private boolean writingEncryptedData;

    private Lock sslLock = new ReentrantLock();

    /**
     * Create a new SSL Handler, and initialize it.
     *
     * @param sslContext
     * @throws SSLException
     */
    /* no qualifier */SslHandler(SslFilter sslFilter, IoSession session) throws SSLException {
        this.sslFilter = sslFilter;
        this.session = session;
    }

    /**
     * Initialize the SSL handshake.
     *
     * @throws SSLException If the underlying SSLEngine handshake initialization failed
     */
    /* no qualifier */void init() throws SSLException {
        if (sslEngine != null) {
            // We already have a SSL engine created, no need to create a new one
            return;
        }

        LOGGER.debug("{} Initializing the SSL Handler", sslFilter.getSessionInfo(session));

        InetSocketAddress peer = (InetSocketAddress) session.getAttribute(SslFilter.PEER_ADDRESS);

        // Create the SSL engine here
        if (peer == null) {
            sslEngine = sslFilter.sslContext.createSSLEngine();
        } else {
            sslEngine = sslFilter.sslContext.createSSLEngine(peer.getHostName(), peer.getPort());
        }

        // Initialize the engine in client mode if necessary
        sslEngine.setUseClientMode(sslFilter.isUseClientMode());

        // Initialize the different SslEngine modes
        if (!sslEngine.getUseClientMode()) {
            // Those parameters are only valid when in server mode
            if (sslFilter.isWantClientAuth()) {
                sslEngine.setWantClientAuth(true);
            }

            if (sslFilter.isNeedClientAuth()) {
                sslEngine.setNeedClientAuth(true);
            }
        }

        // Set the cipher suite to use by this SslEngine instance
        if (sslFilter.getEnabledCipherSuites() != null) {
            sslEngine.setEnabledCipherSuites(sslFilter.getEnabledCipherSuites());
        }

        // Set the list of enabled protocols
        if (sslFilter.getEnabledProtocols() != null) {
            sslEngine.setEnabledProtocols(sslFilter.getEnabledProtocols());
        }

        // TODO : we may not need to call this method...
        // However, if we don't call it here, the tests are failing. Why?
        sslEngine.beginHandshake();

        handshakeStatus = sslEngine.getHandshakeStatus();

        // Default value
        writingEncryptedData = false;

        // We haven't yet started a SSL negotiation
        // set the flags accordingly
        firstSSLNegociation = true;
        handshakeComplete = false;

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("{} SSL Handler Initialization done.", sslFilter.getSessionInfo(session));
        }
    }

    /**
     * Release allocated buffers.
     */
    /* no qualifier */void destroy() {
        if (sslEngine == null) {
            return;
        }

        // Close inbound and flush all remaining data if available.
        try {
            sslEngine.closeInbound();
        } catch (SSLException e) {
            LOGGER.debug("Unexpected exception from SSLEngine.closeInbound().", e);
        }

        if (outNetBuffer != null) {
            outNetBuffer.capacity(sslEngine.getSession().getPacketBufferSize());
        } else {
            createOutNetBuffer(0);
        }
        try {
            do {
                outNetBuffer.clear();
            } while (sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()).bytesProduced() > 0);
        } catch (SSLException e) {
            // Ignore.
        } finally {
            outNetBuffer.free();
            outNetBuffer = null;
        }

        sslEngine.closeOutbound();
        sslEngine = null;

        preHandshakeEventQueue.clear();
    }

    /**
     * @return The SSL filter which has created this handler
     */
    /* no qualifier */SslFilter getSslFilter() {
        return sslFilter;
    }

    /* no qualifier */IoSession getSession() {
        return session;
    }

    /**
     * Check if we are writing encrypted data.
     */
    /* no qualifier */boolean isWritingEncryptedData() {
        return writingEncryptedData;
    }

    /**
     * Check if handshake is completed.
     */
    /* no qualifier */boolean isHandshakeComplete() {
        return handshakeComplete;
    }

    /* no qualifier */boolean isInboundDone() {
        return sslEngine == null || sslEngine.isInboundDone();
    }

    /* no qualifier */boolean isOutboundDone() {
        return sslEngine == null || sslEngine.isOutboundDone();
    }

    /**
     * Check if there is any need to complete handshake.
     */
    /* no qualifier */boolean needToCompleteHandshake() {
        return handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !isInboundDone();
    }

    /* no qualifier */void schedulePreHandshakeWriteRequest(NextFilter nextFilter, WriteRequest writeRequest) {
        preHandshakeEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest));
    }

    /* no qualifier */void flushPreHandshakeEvents() throws SSLException {
        IoFilterEvent scheduledWrite;

        while ((scheduledWrite = preHandshakeEventQueue.poll()) != null) {
            sslFilter
            .filterWrite(scheduledWrite.getNextFilter(), session, (WriteRequest) scheduledWrite.getParameter());
        }
    }

    /* no qualifier */void scheduleFilterWrite(NextFilter nextFilter, WriteRequest writeRequest) {
        filterWriteEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest));
    }

    /**
     * Push the newly received data into a queue, waiting for the SSL session
     * to be fully established
     *
     * @param nextFilter The next filter to call
     * @param message The incoming data
     */
    /* no qualifier */void scheduleMessageReceived(NextFilter nextFilter, Object message) {
        messageReceivedEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message));
    }

    /* no qualifier */void flushScheduledEvents() {
        // Fire events only when no lock is hold for this handler.
        if (Thread.holdsLock(this)) {
            return;
        }

        IoFilterEvent event;

        // We need synchronization here inevitably because filterWrite can be
        // called simultaneously and cause 'bad record MAC' integrity error.
        sslLock.lock();

        try {
            while ((event = filterWriteEventQueue.poll()) != null) {
                NextFilter nextFilter = event.getNextFilter();
                nextFilter.filterWrite(session, (WriteRequest) event.getParameter());
            }

            while ((event = messageReceivedEventQueue.poll()) != null) {
                NextFilter nextFilter = event.getNextFilter();
                nextFilter.messageReceived(session, event.getParameter());
            }
        } finally {
            sslLock.unlock();
        }
    }

    /**
     * Call when data are read from net. It will perform the initial hanshake or decrypt
     * the data if SSL has been initialiaed.
     *
     * @param buf buffer to decrypt
     * @param nextFilter Next filter in chain
     * @throws SSLException on errors
     */
    /* no qualifier */void messageReceived(NextFilter nextFilter, ByteBuffer buf) throws SSLException {
        if (LOGGER.isDebugEnabled()) {
            if (!isOutboundDone()) {
                LOGGER.debug("{} Processing the received message", sslFilter.getSessionInfo(session));
            } else {
                LOGGER.debug("{} Processing the received message", sslFilter.getSessionInfo(session));
            }
        }

        // append buf to inNetBuffer
        if (inNetBuffer == null) {
            inNetBuffer = IoBuffer.allocate(buf.remaining()).setAutoExpand(true);
        }

        inNetBuffer.put(buf);

        if (!handshakeComplete) {
            handshake(nextFilter);
        } else {
            // Prepare the net data for reading.
            inNetBuffer.flip();

            if (!inNetBuffer.hasRemaining()) {
                return;
            }

            SSLEngineResult res = unwrap();

            // prepare to be written again
            if (inNetBuffer.hasRemaining()) {
                inNetBuffer.compact();
            } else {
                inNetBuffer.free();
                inNetBuffer = null;
            }

            checkStatus(res);

            renegotiateIfNeeded(nextFilter, res);
        }

        if (isInboundDone()) {
            // Rewind the MINA buffer if not all data is processed and inbound
            // is finished.
            int inNetBufferPosition = inNetBuffer == null ? 0 : inNetBuffer.position();
            buf.position(buf.position() - inNetBufferPosition);

            if (inNetBuffer != null) {
                inNetBuffer.free();
                inNetBuffer = null;
            }
        }
    }

    /**
     * Get decrypted application data.
     *
     * @return buffer with data
     */
    /* no qualifier */IoBuffer fetchAppBuffer() {
        if (this.appBuffer == null) {
            return IoBuffer.allocate(0);
        } else {
            IoBuffer appBuffer = this.appBuffer.flip();
            this.appBuffer = null;

            return appBuffer;
        }
    }

    /**
     * Get encrypted data to be sent.
     *
     * @return buffer with data
     */
    /* no qualifier */IoBuffer fetchOutNetBuffer() {
        IoBuffer answer = outNetBuffer;
        if (answer == null) {
            return emptyBuffer;
        }

        outNetBuffer = null;
        return answer.shrink();
    }

    /**
     * Encrypt provided buffer. Encrypted data returned by getOutNetBuffer().
     *
     * @param src
     *            data to encrypt
     * @throws SSLException
     *             on errors
     */
    /* no qualifier */void encrypt(ByteBuffer src) throws SSLException {
        if (!handshakeComplete) {
            throw new IllegalStateException();
        }

        if (!src.hasRemaining()) {
            if (outNetBuffer == null) {
                outNetBuffer = emptyBuffer;
            }
            return;
        }

        createOutNetBuffer(src.remaining());

        // Loop until there is no more data in src
        while (src.hasRemaining()) {

            SSLEngineResult result = sslEngine.wrap(src, outNetBuffer.buf());
            if (result.getStatus() == SSLEngineResult.Status.OK) {
                if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
                    doTasks();
                }
            } else if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
                outNetBuffer.capacity(outNetBuffer.capacity() << 1);
                outNetBuffer.limit(outNetBuffer.capacity());
            } else {
                throw new SSLException("SSLEngine error during encrypt: " + result.getStatus() + " src: " + src
                        + "outNetBuffer: " + outNetBuffer);
            }
        }

        outNetBuffer.flip();
    }

    /**
     * Start SSL shutdown process.
     *
     * @return <tt>true</tt> if shutdown process is started. <tt>false</tt> if
     *         shutdown process is already finished.
     * @throws SSLException
     *             on errors
     */
    /* no qualifier */boolean closeOutbound() throws SSLException {
        if (sslEngine == null || sslEngine.isOutboundDone()) {
            return false;
        }

        sslEngine.closeOutbound();

        createOutNetBuffer(0);
        SSLEngineResult result;

        for (;;) {
            result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf());
            if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
                outNetBuffer.capacity(outNetBuffer.capacity() << 1);
                outNetBuffer.limit(outNetBuffer.capacity());
            } else {
                break;
            }
        }

        if (result.getStatus() != SSLEngineResult.Status.CLOSED) {
            throw new SSLException("Improper close state: " + result);
        }

        outNetBuffer.flip();

        return true;
    }

    /**
     * @param res
     * @throws SSLException
     */
    private void checkStatus(SSLEngineResult res) throws SSLException {

        SSLEngineResult.Status status = res.getStatus();

        /*
         * The status may be:
         * OK - Normal operation
         * OVERFLOW - Should never happen since the application buffer is sized to hold the maximum
         * packet size.
         * UNDERFLOW - Need to read more data from the socket. It's normal.
         * CLOSED - The other peer closed the socket. Also normal.
         */
        if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
            throw new SSLException("SSLEngine error during decrypt: " + status + " inNetBuffer: " + inNetBuffer
                    + "appBuffer: " + appBuffer);
        }
    }

    /**
     * Perform any handshaking processing.
     */
    /* no qualifier */void handshake(NextFilter nextFilter) throws SSLException {
        for (;;) {
            switch (handshakeStatus) {
            case FINISHED:
            case NOT_HANDSHAKING:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("{} processing the FINISHED state", sslFilter.getSessionInfo(session));
                }

                session.setAttribute(SslFilter.SSL_SESSION, sslEngine.getSession());
                handshakeComplete = true;

                // Send the SECURE message only if it's the first SSL handshake
                if (firstSSLNegociation && session.containsAttribute(SslFilter.USE_NOTIFICATION)) {
                    // SESSION_SECURED is fired only when it's the first handshake
                    firstSSLNegociation = false;
                    scheduleMessageReceived(nextFilter, SslFilter.SESSION_SECURED);
                }

                if (LOGGER.isDebugEnabled()) {
                    if (!isOutboundDone()) {
                        LOGGER.debug("{} is now secured", sslFilter.getSessionInfo(session));
                    } else {
                        LOGGER.debug("{} is not secured yet", sslFilter.getSessionInfo(session));
                    }
                }

                return;

            case NEED_TASK:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("{} processing the NEED_TASK state", sslFilter.getSessionInfo(session));
                }

                handshakeStatus = doTasks();
                break;

            case NEED_UNWRAP:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("{} processing the NEED_UNWRAP state", sslFilter.getSessionInfo(session));
                }
                // we need more data read
                SSLEngineResult.Status status = unwrapHandshake(nextFilter);

                if (status == SSLEngineResult.Status.BUFFER_UNDERFLOW
                        && handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED || isInboundDone()) {
                    // We need more data or the session is closed
                    return;
                }

                break;

            case NEED_WRAP:
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("{} processing the NEED_WRAP state", sslFilter.getSessionInfo(session));
                }

                // First make sure that the out buffer is completely empty.
                // Since we
                // cannot call wrap with data left on the buffer
                if (outNetBuffer != null && outNetBuffer.hasRemaining()) {
                    return;
                }

                SSLEngineResult result;
                createOutNetBuffer(0);

                for (;;) {
                    result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf());
                    if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
                        outNetBuffer.capacity(outNetBuffer.capacity() << 1);
                        outNetBuffer.limit(outNetBuffer.capacity());
                    } else {
                        break;
                    }
                }

                outNetBuffer.flip();
                handshakeStatus = result.getHandshakeStatus();
                writeNetBuffer(nextFilter);
                break;

            default:
                String msg = "Invalid Handshaking State" + handshakeStatus
                + " while processing the Handshake for session " + session.getId();
                LOGGER.error(msg);
                throw new IllegalStateException(msg);
            }
        }
    }

    private void createOutNetBuffer(int expectedRemaining) {
        // SSLEngine requires us to allocate unnecessarily big buffer
        // even for small data. *Shrug*
        int capacity = Math.max(expectedRemaining, sslEngine.getSession().getPacketBufferSize());

        if (outNetBuffer != null) {
            outNetBuffer.capacity(capacity);
        } else {
            outNetBuffer = IoBuffer.allocate(capacity).minimumCapacity(0);
        }
    }

    /* no qualifier */WriteFuture writeNetBuffer(NextFilter nextFilter) throws SSLException {
        // Check if any net data needed to be writen
        if (outNetBuffer == null || !outNetBuffer.hasRemaining()) {
            // no; bail out
            return null;
        }

        // set flag that we are writing encrypted data
        // (used in SSLFilter.filterWrite())
        writingEncryptedData = true;

        // write net data
        WriteFuture writeFuture = null;

        try {
            IoBuffer writeBuffer = fetchOutNetBuffer();
            writeFuture = new DefaultWriteFuture(session);
            sslFilter.filterWrite(nextFilter, session, new DefaultWriteRequest(writeBuffer, writeFuture));

            // loop while more writes required to complete handshake
            while (needToCompleteHandshake()) {
                try {
                    handshake(nextFilter);
                } catch (SSLException ssle) {
                    SSLException newSsle = new SSLHandshakeException("SSL handshake failed.");
                    newSsle.initCause(ssle);
                    throw newSsle;
                }

                IoBuffer outNetBuffer = fetchOutNetBuffer();
                if (outNetBuffer != null && outNetBuffer.hasRemaining()) {
                    writeFuture = new DefaultWriteFuture(session);
                    sslFilter.filterWrite(nextFilter, session, new DefaultWriteRequest(outNetBuffer, writeFuture));
                }
            }
        } finally {
            writingEncryptedData = false;
        }

        return writeFuture;
    }

    private SSLEngineResult.Status unwrapHandshake(NextFilter nextFilter) throws SSLException {
        // Prepare the net data for reading.
        if (inNetBuffer != null) {
            inNetBuffer.flip();
        }

        if ((inNetBuffer == null) || !inNetBuffer.hasRemaining()) {
            // Need more data.
            return SSLEngineResult.Status.BUFFER_UNDERFLOW;
        }

        SSLEngineResult res = unwrap();
        handshakeStatus = res.getHandshakeStatus();

        checkStatus(res);

        // If handshake finished, no data was produced, and the status is still
        // ok, try to unwrap more
        if ((handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED)
                && (res.getStatus() == SSLEngineResult.Status.OK)
                && inNetBuffer.hasRemaining()) {
            res = unwrap();

            // prepare to be written again
            if (inNetBuffer.hasRemaining()) {
                inNetBuffer.compact();
            } else {
                inNetBuffer.free();
                inNetBuffer = null;
            }

            renegotiateIfNeeded(nextFilter, res);
        } else {
            // prepare to be written again
            if (inNetBuffer.hasRemaining()) {
                inNetBuffer.compact();
            } else {
                inNetBuffer.free();
                inNetBuffer = null;
            }
        }

        return res.getStatus();
    }

    private void renegotiateIfNeeded(NextFilter nextFilter, SSLEngineResult res) throws SSLException {
        if ((res.getStatus() != SSLEngineResult.Status.CLOSED)
                && (res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW)
                && (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) {
            // Renegotiation required.
            handshakeComplete = false;
            handshakeStatus = res.getHandshakeStatus();
            handshake(nextFilter);
        }
    }

    /**
     * Decrypt the incoming buffer and move the decrypted data to an
     * application buffer.
     */
    private SSLEngineResult unwrap() throws SSLException {
        // We first have to create the application buffer if it does not exist
        if (appBuffer == null) {
            appBuffer = IoBuffer.allocate(inNetBuffer.remaining());
        } else {
            // We already have one, just add the new data into it
            appBuffer.expand(inNetBuffer.remaining());
        }

        SSLEngineResult res;

        Status status = null;
        HandshakeStatus handshakeStatus = null;

        do {
            // Decode the incoming data
            res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf());
            status = res.getStatus();

            // We can be processing the Handshake
            handshakeStatus = res.getHandshakeStatus();

            if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
                // We have to grow the target buffer, it's too small.
                // Then we can call the unwrap method again
                appBuffer.capacity(appBuffer.capacity() << 1);
                appBuffer.limit(appBuffer.capacity());
                continue;
            }
        } while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW))
                && ((handshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) || (handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)));

        return res;
    }

    /**
     * Do all the outstanding handshake tasks in the current Thread.
     */
    private SSLEngineResult.HandshakeStatus doTasks() {
        /*
         * We could run this in a separate thread, but I don't see the need for
         * this when used from SSLFilter. Use thread filters in MINA instead?
         */
        Runnable runnable;
        while ((runnable = sslEngine.getDelegatedTask()) != null) {
            // TODO : we may have to use a thread pool here to improve the
            // performances
            runnable.run();
        }
        return sslEngine.getHandshakeStatus();
    }

    /**
     * Creates a new MINA buffer that is a deep copy of the remaining bytes in
     * the given buffer (between index buf.position() and buf.limit())
     *
     * @param src
     *            the buffer to copy
     * @return the new buffer, ready to read from
     */
    /* no qualifier */static IoBuffer copy(ByteBuffer src) {
        IoBuffer copy = IoBuffer.allocate(src.remaining());
        copy.put(src);
        copy.flip();
        return copy;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();

        sb.append("SSLStatus <");

        if (handshakeComplete) {
            sb.append("SSL established");
        } else {
            sb.append("Processing Handshake").append("; ");
            sb.append("Status : ").append(handshakeStatus).append("; ");
        }

        sb.append(", ");
        sb.append("HandshakeComplete :").append(handshakeComplete).append(", ");
        sb.append(">");

        return sb.toString();
    }

    /**
     * Free the allocated buffers
     */
    /* no qualifier */void release() {
        if (inNetBuffer != null) {
            inNetBuffer.free();
            inNetBuffer = null;
        }

        if (outNetBuffer != null) {
            outNetBuffer.free();
            outNetBuffer = null;
        }
    }
}


text:
using ESRI.ArcLogistics.Routing;

namespace ESRI.ArcLogistics.Tracking.TrackingService.Requests
{
    /// <summary>
    /// Request for feature layer "Query" operation.
    /// </summary>
    internal sealed class QueryRequest : RequestBase
    {
        /// <summary>
        /// Gets or sets a list of object IDs to return features for.
        /// </summary>
        [QueryParameter(Name = "objectIds")]
        public string ObjectIDs { get; set; }

        /// <summary>
        /// Gets or sets a where clause to filter returned features with.
        /// </summary>
        [QueryParameter(Name = "where")]
        public string WhereClause { get; set; }

        /// <summary>
        /// Gets or sets a list of fields to be returned for feature objects.
        /// </summary>
        [QueryParameter(Name = "outFields")]
        public string ReturnFields { get; set; }

        /// <summary>
        /// Gets or sets a value indicating if only object IDs should be returned.
        /// </summary>
        [QueryParameter(Name = "returnIdsOnly")]
        public bool ReturnIDsOnly { get; set; }

        /// <summary>
        /// Gets or sets a value indicating if feature geometry should be returned.
        /// </summary>
        [QueryParameter(Name = "returnGeometry")]
        public bool ReturnGeometry { get; set; }
    }
}


text:
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings
import uuid

class Migration(migrations.Migration):

    dependencies = [
        ('authtools', '__first__'),
    ]

    operations = [
        migrations.CreateModel(
            name='Profile',
            fields=[
                ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, serialize=False, primary_key=True)),
                ('slug', models.UUIDField(editable=False, default=uuid.uuid4, blank=True)),
                ('picture', models.ImageField(verbose_name='Profile picture', null=True, upload_to='profile_pics/%Y-%m-%d/', blank=True)),
                ('bio', models.CharField(verbose_name='Short Bio', max_length=200, null=True, blank=True)),
                ('email_verified', models.BooleanField(verbose_name='Email verified', default=False)),
            ],
            options={
                'abstract': False,
            },
        ),
    ]


text:
#ifndef __PORTABLEFONTINSTANCE_H
#define __PORTABLEFONTINSTANCE_H

#include <stdio.h>

#include "layout/LETypes.h"
#include "layout/LEFontInstance.h"

#include "FontTableCache.h"

#include "sfnt.h"
#include "cmaps.h"

class PortableFontInstance : public LEFontInstance, protected FontTableCache
{
private:
    FILE *fFile;

    float     fPointSize;
    le_int32  fUnitsPerEM;
    le_uint32 fFontChecksum;
    le_int32  fAscent;
    le_int32  fDescent;
    le_int32  fLeading;

    const SFNTDirectory *fDirectory;
    le_uint16 fDirPower;
    le_uint16 fDirExtra;

    float fDeviceScaleX;
    float fDeviceScaleY;

    const NAMETable *fNAMETable;
    le_uint16 fNameCount;
    le_uint16 fNameStringOffset;

    CMAPMapper *fCMAPMapper;

    const HMTXTable *fHMTXTable;
    le_uint16 fNumGlyphs;
    le_uint16 fNumLongHorMetrics;

    static le_int8 highBit(le_int32 value);

    const DirectoryEntry *findTable(LETag tag) const;
    const void *readTable(LETag tag, le_uint32 *length) const;
    void getMetrics();

    CMAPMapper *findUnicodeMapper();

protected:
    const void *readFontTable(LETag tableTag) const { size_t ignored; return readFontTable(tableTag, ignored); }
    const void *readFontTable(LETag tableTag, size_t &length) const;

public:
    PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status);

    virtual ~PortableFontInstance();

    virtual const void *getFontTable(LETag tableTag, size_t &length) const;

    virtual const char *getNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;

    virtual const LEUnicode16 *getUnicodeNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;

    virtual void deleteNameString(const char *name) const;

    virtual void deleteNameString(const LEUnicode16 *name) const;

    virtual le_int32 getUnitsPerEM() const;

    virtual le_uint32 getFontChecksum() const;

    virtual le_uint32 getRawChecksum() const;

    virtual le_int32 getAscent() const;

    virtual le_int32 getDescent() const;

    virtual le_int32 getLeading() const;

    // We really want to inherit this method from the superclass, but some compilers
    // issue a warning if we don't implement it...
    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const;

    // We really want to inherit this method from the superclass, but some compilers
    // issue a warning if we don't implement it...
    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const;

    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const;

    virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;

    virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;

    float getXPixelsPerEm() const;

    float getYPixelsPerEm() const;

    float getScaleFactorX() const;

    float getScaleFactorY() const;

};

#endif