text:
.class final Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;
.super Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
.source "AtomicReferenceFieldUpdater.java"

# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
    value = Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x1a
    name = "AtomicReferenceFieldUpdaterImpl"
.end annotation

.annotation system Ldalvik/annotation/Signature;
    value = {
        "<T:",
        "Ljava/lang/Object;",
        "V:",
        "Ljava/lang/Object;",
        ">",
        "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater",
        "<TT;TV;>;"
    }
.end annotation

# static fields
.field private static final unsafe:Lsun/misc/Unsafe;

# instance fields
.field private final cclass:Ljava/lang/Class;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "Ljava/lang/Class",
            "<*>;"
        }
    .end annotation
.end field

.field private final offset:J

.field private final tclass:Ljava/lang/Class;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "Ljava/lang/Class",
            "<TT;>;"
        }
    .end annotation
.end field

.field private final vclass:Ljava/lang/Class;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "Ljava/lang/Class",
            "<TV;>;"
        }
    .end annotation
.end field

# direct methods
.method static constructor <clinit>()V
    .locals 1

    .prologue
    .line 157
    invoke-static {}, Lsun/misc/Unsafe;->getUnsafe()Lsun/misc/Unsafe;

    move-result-object v0

    sput-object v0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    return-void
.end method

.method constructor <init>(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)V
    .locals 8
    .param p3, "fieldName"    # Ljava/lang/String;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Ljava/lang/Class",
            "<TT;>;",
            "Ljava/lang/Class",
            "<TV;>;",
            "Ljava/lang/String;",
            ")V"
        }
    .end annotation

    .prologue
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "tclass":Ljava/lang/Class;, "Ljava/lang/Class<TT;>;"
    .local p2, "vclass":Ljava/lang/Class;, "Ljava/lang/Class<TV;>;"
    const/4 v5, 0x0

    .line 177
    invoke-direct {p0}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;-><init>()V

    .line 183
    :try_start_0
    invoke-virtual {p1, p3}, Ljava/lang/Class;->getDeclaredField(Ljava/lang/String;)Ljava/lang/reflect/Field;

    move-result-object v2

    .line 184
    .local v2, "field":Ljava/lang/reflect/Field;
    invoke-static {}, Ldalvik/system/VMStack;->getStackClass2()Ljava/lang/Class;

    move-result-object v0

    .line 185
    .local v0, "caller":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    invoke-virtual {v2}, Ljava/lang/reflect/Field;->getModifiers()I

    move-result v4

    .line 196
    .local v4, "modifiers":I
    invoke-virtual {v2}, Ljava/lang/reflect/Field;->getType()Ljava/lang/Class;
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

    move-result-object v3

    .line 205
    .local v3, "fieldClass":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    if-eq p2, v3, :cond_0

    .line 206
    new-instance v5, Ljava/lang/ClassCastException;

    invoke-direct {v5}, Ljava/lang/ClassCastException;-><init>()V

    throw v5

    .line 201
    .end local v0    # "caller":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    .end local v2    # "field":Ljava/lang/reflect/Field;
    .end local v3    # "fieldClass":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    .end local v4    # "modifiers":I
    :catch_0
    move-exception v1

    .line 202
    .local v1, "ex":Ljava/lang/Exception;
    new-instance v5, Ljava/lang/RuntimeException;

    invoke-direct {v5, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/Throwable;)V

    throw v5

    .line 208
    .end local v1    # "ex":Ljava/lang/Exception;
    .restart local v0    # "caller":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    .restart local v2    # "field":Ljava/lang/reflect/Field;
    .restart local v3    # "fieldClass":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    .restart local v4    # "modifiers":I
    :cond_0
    invoke-static {v4}, Ljava/lang/reflect/Modifier;->isVolatile(I)Z

    move-result v6

    if-nez v6, :cond_1

    .line 209
    new-instance v5, Ljava/lang/IllegalArgumentException;

    const-string v6, "Must be volatile type"

    invoke-direct {v5, v6}, Ljava/lang/IllegalArgumentException;-><init>(Ljava/lang/String;)V

    throw v5

    .line 211
    :cond_1
    invoke-static {v4}, Ljava/lang/reflect/Modifier;->isProtected(I)Z

    move-result v6

    if-eqz v6, :cond_2

    if-eq v0, p1, :cond_2

    .end local v0    # "caller":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    :goto_0
    iput-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    .line 213
    iput-object p1, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    .line 214
    const-class v6, Ljava/lang/Object;

    if-ne p2, v6, :cond_3

    .line 215
    iput-object v5, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    .line 218
    :goto_1
    sget-object v5, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    invoke-virtual {v5, v2}, Lsun/misc/Unsafe;->objectFieldOffset(Ljava/lang/reflect/Field;)J

    move-result-wide v6

    iput-wide v6, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J

    .line 219
    return-void

    .restart local v0    # "caller":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    :cond_2
    move-object v0, v5

    .line 211
    goto :goto_0

    .line 217
    .end local v0    # "caller":Ljava/lang/Class;, "Ljava/lang/Class<*>;"
    :cond_3
    iput-object p2, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    goto :goto_1
.end method

.method private ensureProtectedAccess(Ljava/lang/Object;)V
    .locals 4
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;)V"
        }
    .end annotation

    .prologue
    .line 296
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    invoke-virtual {v0, p1}, Ljava/lang/Class;->isInstance(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_0

    .line 297
    return-void

    .line 299
    :cond_0
    new-instance v0, Ljava/lang/RuntimeException;

    new-instance v1, Ljava/lang/IllegalAccessException;

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string v3, "Class "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    iget-object v3, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;

    move-result-object v3

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    const-string v3, " can not access a protected member of class "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    iget-object v3, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;

    move-result-object v3

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    const-string v3, " using an instance of "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v3

    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;

    move-result-object v3

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/IllegalAccessException;-><init>(Ljava/lang/String;)V

    invoke-direct {v0, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/Throwable;)V

    throw v0
.end method

# virtual methods
.method public compareAndSet(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z
    .locals 6
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;TV;TV;)Z"
        }
    .end annotation

    .prologue
    .line 256
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    .local p2, "expect":Ljava/lang/Object;, "TV;"
    .local p3, "update":Ljava/lang/Object;, "TV;"
    if-eqz p1, :cond_0

    invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v0

    iget-object v1, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    if-ne v0, v1, :cond_0

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-nez v0, :cond_0

    if-eqz p3, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    invoke-virtual {p3}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v1

    if-eq v0, v1, :cond_1

    .line 259
    :cond_0
    invoke-virtual {p0, p1, p3}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->updateCheck(Ljava/lang/Object;Ljava/lang/Object;)V

    .line 260
    :cond_1
    sget-object v0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    iget-wide v2, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J

    move-object v1, p1

    move-object v4, p2

    move-object v5, p3

    invoke-virtual/range {v0 .. v5}, Lsun/misc/Unsafe;->compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z

    move-result v0

    return v0
.end method

.method public get(Ljava/lang/Object;)Ljava/lang/Object;
    .locals 4
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;)TV;"
        }
    .end annotation

    .prologue
    .line 290
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    if-eqz p1, :cond_0

    invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v0

    iget-object v1, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    if-ne v0, v1, :cond_0

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    .line 291
    :cond_0
    invoke-virtual {p0, p1}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->targetCheck(Ljava/lang/Object;)V

    .line 292
    :cond_1
    sget-object v0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    iget-wide v2, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J

    invoke-virtual {v0, p1, v2, v3}, Lsun/misc/Unsafe;->getObjectVolatile(Ljava/lang/Object;J)Ljava/lang/Object;

    move-result-object v0

    return-object v0
.end method

.method public lazySet(Ljava/lang/Object;Ljava/lang/Object;)V
    .locals 4
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;TV;)V"
        }
    .end annotation

    .prologue
    .line 281
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    .local p2, "newValue":Ljava/lang/Object;, "TV;"
    if-eqz p1, :cond_0

    invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v0

    iget-object v1, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    if-ne v0, v1, :cond_0

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-nez v0, :cond_0

    if-eqz p2, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    invoke-virtual {p2}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v1

    if-eq v0, v1, :cond_1

    .line 284
    :cond_0
    invoke-virtual {p0, p1, p2}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->updateCheck(Ljava/lang/Object;Ljava/lang/Object;)V

    .line 285
    :cond_1
    sget-object v0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    iget-wide v2, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J

    invoke-virtual {v0, p1, v2, v3, p2}, Lsun/misc/Unsafe;->putOrderedObject(Ljava/lang/Object;JLjava/lang/Object;)V

    .line 286
    return-void
.end method

.method public set(Ljava/lang/Object;Ljava/lang/Object;)V
    .locals 4
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;TV;)V"
        }
    .end annotation

    .prologue
    .line 273
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    .local p2, "newValue":Ljava/lang/Object;, "TV;"
    if-eqz p1, :cond_0

    invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v0

    iget-object v1, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    if-ne v0, v1, :cond_0

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-nez v0, :cond_0

    if-eqz p2, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    invoke-virtual {p2}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v1

    if-eq v0, v1, :cond_1

    .line 276
    :cond_0
    invoke-virtual {p0, p1, p2}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->updateCheck(Ljava/lang/Object;Ljava/lang/Object;)V

    .line 277
    :cond_1
    sget-object v0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    iget-wide v2, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J

    invoke-virtual {v0, p1, v2, v3, p2}, Lsun/misc/Unsafe;->putObjectVolatile(Ljava/lang/Object;JLjava/lang/Object;)V

    .line 278
    return-void
.end method

.method targetCheck(Ljava/lang/Object;)V
    .locals 1
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;)V"
        }
    .end annotation

    .prologue
    .line 241
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    invoke-virtual {v0, p1}, Ljava/lang/Class;->isInstance(Ljava/lang/Object;)Z

    move-result v0

    if-nez v0, :cond_0

    .line 242
    new-instance v0, Ljava/lang/ClassCastException;

    invoke-direct {v0}, Ljava/lang/ClassCastException;-><init>()V

    throw v0

    .line 243
    :cond_0
    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    .line 244
    invoke-direct {p0, p1}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->ensureProtectedAccess(Ljava/lang/Object;)V

    .line 245
    :cond_1
    return-void
.end method

.method updateCheck(Ljava/lang/Object;Ljava/lang/Object;)V
    .locals 1
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;TV;)V"
        }
    .end annotation

    .prologue
    .line 248
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    .local p2, "update":Ljava/lang/Object;, "TV;"
    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    invoke-virtual {v0, p1}, Ljava/lang/Class;->isInstance(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_0

    if-eqz p2, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    invoke-virtual {v0, p2}, Ljava/lang/Class;->isInstance(Ljava/lang/Object;)Z

    move-result v0

    if-nez v0, :cond_1

    .line 250
    :cond_0
    new-instance v0, Ljava/lang/ClassCastException;

    invoke-direct {v0}, Ljava/lang/ClassCastException;-><init>()V

    throw v0

    .line 251
    :cond_1
    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-eqz v0, :cond_2

    .line 252
    invoke-direct {p0, p1}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->ensureProtectedAccess(Ljava/lang/Object;)V

    .line 253
    :cond_2
    return-void
.end method

.method public weakCompareAndSet(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z
    .locals 6
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(TT;TV;TV;)Z"
        }
    .end annotation

    .prologue
    .line 265
    .local p0, "this":Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;, "Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl<TT;TV;>;"
    .local p1, "obj":Ljava/lang/Object;, "TT;"
    .local p2, "expect":Ljava/lang/Object;, "TV;"
    .local p3, "update":Ljava/lang/Object;, "TV;"
    if-eqz p1, :cond_0

    invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v0

    iget-object v1, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;

    if-ne v0, v1, :cond_0

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;

    if-nez v0, :cond_0

    if-eqz p3, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    if-eqz v0, :cond_1

    iget-object v0, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;

    invoke-virtual {p3}, Ljava/lang/Object;->getClass()Ljava/lang/Class;

    move-result-object v1

    if-eq v0, v1, :cond_1

    .line 268
    :cond_0
    invoke-virtual {p0, p1, p3}, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->updateCheck(Ljava/lang/Object;Ljava/lang/Object;)V

    .line 269
    :cond_1
    sget-object v0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->unsafe:Lsun/misc/Unsafe;

    iget-wide v2, p0, Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J

    move-object v1, p1

    move-object v4, p2

    move-object v5, p3

    invoke-virtual/range {v0 .. v5}, Lsun/misc/Unsafe;->compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z

    move-result v0

    return v0
.end method


text:
using System;

namespace Resque
{
    class ResqueException : Exception
    {
        public ResqueException(string message) : base(message)
        {

        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package com.ichmed.trinketeers.entity.pickup;

import com.ichmed.trinketeers.entity.Player;
import com.ichmed.trinketeers.world.World;

public class Coin extends Pickup
{
	public Coin(World w)
	{
		super(w);
		this.entityType = "coin";
		this.size.x = this.size.y = 0.035f;
		this.movementDelay = 25;
	}

	@Override
	public boolean pickUp(World w, Player p)
	{
		p.coins++;
		return true;
	}

}


text:
import numpy as np
import networkx as nx
# calculate the length of a generator
def generator_size(g):
    return sum(1 for x in g)
def cliqstr(g):
    # finding the maximal cliques using bron kerbosch algorithm in networkx
    cliq = nx.find_cliques(g)
    # converting the generator type to a 2d list
    counter = 0
    cliques = []
    for i in nx.find_cliques(g):
        if len(i)>1:
            cliques.append(i)
            counter += 1
    #assert cliques_size == counter
    print cliques
    cliques_size = counter
    vecd = np.zeros(counter)
    matA = np.zeros((counter, counter))
    cliq_list = [counter]
    # Calculating matX and vector D in the formula
    for i in range(counter):
        for j in range(counter):
            matA[i,j] = len(set(cliques[i]).intersection(cliques[j]))*(len(set(cliques[i]).intersection(cliques[j])) -1)/2
        matA[i,i] = len(cliques[i]) * (len(cliques[i]) - 1) / 2
        for j in cliques[i]:
            for k in cliques[i]:
                if j!=k:
                    if g.has_edge(j,k):
                         vecd[i] += 1
    vecd /= 2
    # Solving the system of equations
    #eps = 0.0000000001
    #print matA
    print vecd
    Mu = np.linalg.tensorsolve(matA,vecd)
    return Mu


text:
<?xml version="1.0" encoding="UTF-8"?>
<Tokens version="1.0">
	<File path="Classes/AWSKinesisDescribeStreamInput.html">

		<Token>
			<TokenIdentifier>//apple_ref/occ/cl/AWSKinesisDescribeStreamInput</TokenIdentifier>
			<Abstract type="html">
Represents the input for DescribeStream.

Required parameters: [StreamName]</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/AWSKinesisDescribeStreamInput/setExclusiveStartShardId:</TokenIdentifier>
			<Abstract type="html">
The shard ID of the shard to start with.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSString *exclusiveStartShardId</Declaration>

			<Anchor>//api/name/exclusiveStartShardId</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/AWSKinesisDescribeStreamInput/exclusiveStartShardId</TokenIdentifier>
			<Abstract type="html">
The shard ID of the shard to start with.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSString *exclusiveStartShardId</Declaration>

			<Anchor>//api/name/exclusiveStartShardId</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/AWSKinesisDescribeStreamInput/exclusiveStartShardId</TokenIdentifier>
			<Abstract type="html">
The shard ID of the shard to start with.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSString *exclusiveStartShardId</Declaration>

			<Anchor>//api/name/exclusiveStartShardId</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/AWSKinesisDescribeStreamInput/setLimit:</TokenIdentifier>
			<Abstract type="html">
The maximum number of shards to return.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSNumber *limit</Declaration>

			<Anchor>//api/name/limit</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/AWSKinesisDescribeStreamInput/limit</TokenIdentifier>
			<Abstract type="html">
The maximum number of shards to return.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSNumber *limit</Declaration>

			<Anchor>//api/name/limit</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/AWSKinesisDescribeStreamInput/limit</TokenIdentifier>
			<Abstract type="html">
The maximum number of shards to return.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSNumber *limit</Declaration>

			<Anchor>//api/name/limit</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/AWSKinesisDescribeStreamInput/setStreamName:</TokenIdentifier>
			<Abstract type="html">
The name of the stream to describe.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSString *streamName</Declaration>

			<Anchor>//api/name/streamName</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/AWSKinesisDescribeStreamInput/streamName</TokenIdentifier>
			<Abstract type="html">
The name of the stream to describe.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSString *streamName</Declaration>

			<Anchor>//api/name/streamName</Anchor>
            <NodeRef refid="962"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/AWSKinesisDescribeStreamInput/streamName</TokenIdentifier>
			<Abstract type="html">
The name of the stream to describe.
</Abstract>
			<DeclaredIn>AWSKinesisModel.h</DeclaredIn>

			<Declaration>@property (nonatomic, strong) NSString *streamName</Declaration>

			<Anchor>//api/name/streamName</Anchor>
            <NodeRef refid="962"/>
		</Token>

	</File>
</Tokens>


text:
<?php

namespace Symfony\Component\Messenger\Handler\Locator;

use Psr\Container\ContainerInterface;
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;

/**
 * @author Miha Vrhovnik <miha.vrhovnik@gmail.com>
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
class ContainerHandlerLocator implements HandlerLocatorInterface
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function resolve($message): callable
    {
        $messageClass = \get_class($message);

        if (null === $handler = $this->resolveFromClass($messageClass)) {
            throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', $messageClass));
        }

        return $handler;
    }

    private function resolveFromClass($class): ?callable
    {
        if ($handler = $this->getHandler($class)) {
            return $handler;
        }

        foreach (class_implements($class, false) as $interface) {
            if ($handler = $this->getHandler($interface)) {
                return $handler;
            }
        }

        foreach (class_parents($class, false) as $parent) {
            if ($handler = $this->getHandler($parent)) {
                return $handler;
            }
        }

        return null;
    }

    private function getHandler($class)
    {
        $handlerKey = 'handler.'.$class;

        return $this->container->has($handlerKey) ? $this->container->get($handlerKey) : null;
    }
}


text:
import bcrypt
import asyncore
from secure_smtpd import SMTPServer, FakeCredentialValidator
from srht.objects import User
from sqlalchemy import or_

class UserValidator(object):
    def validate(self, username, password):
        user = User.query.filter(or_(User.username == username, User.email == username)).first()
        if not user:
            print("Authentication failed for {}, unknown user".format(user))
            return False
        if not user.approved:
            print("Authentication failed for {}, account unapproved".format(user))
            return False
        success = bcrypt.hashpw(password, user.password) == user.password
        if not success:
            print("Authentication failed for {}, bad password".format(user))
        else:
            print("Authentication successful for {}".format(user))
        return success

SMTPServer(
    ('127.0.0.1', 4650),
    None,
    require_authentication=True,
    ssl=False,
    credential_validator=UserValidator(),
).run()


text:
module Gitlab
  module OAuth
    class AuthHash
      attr_reader :auth_hash
      def initialize(auth_hash)
        @auth_hash = auth_hash
      end

      def uid
        @uid ||= Gitlab::Utils.force_utf8(auth_hash.uid.to_s)
      end

      def provider
        @provider ||= Gitlab::Utils.force_utf8(auth_hash.provider.to_s)
      end

      def name
        @name ||= get_info(:name) || "#{get_info(:first_name)} #{get_info(:last_name)}"
      end

      def username
        @username ||= username_and_email[:username].to_s
      end

      def email
        @email ||= username_and_email[:email].to_s
      end

      def password
        @password ||= Gitlab::Utils.force_utf8(Devise.friendly_token[0, 8].downcase)
      end

      def has_email?
        get_info(:email).present?
      end

      private

      def info
        auth_hash.info
      end

      def get_info(key)
        value = info[key]
        Gitlab::Utils.force_utf8(value) if value
        value
      end

      def username_and_email
        @username_and_email ||= begin
          username  = get_info(:username).presence || get_info(:nickname).presence
          email     = get_info(:email).presence

          username ||= generate_username(email)             if email
          email    ||= generate_temporarily_email(username) if username

          {
            username: username,
            email:    email
          }
        end
      end

      # Get the first part of the email address (before @)
      # In addtion in removes illegal characters
      def generate_username(email)
        email.match(/^[^@]*/)[0].mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/, '').to_s
      end

      def generate_temporarily_email(username)
        "temp-email-for-oauth-#{username}@gitlab.localhost"
      end
    end
  end
end


text:
Docker image for Huginn using the production environment and separate container for every process
=================================================

This image runs a linkable [Huginn](https://github.com/huginn/huginn) instance.

It was inspired by the [official docker container for huginn](https://registry.hub.docker.com/u/huginn/huginn)

The scripts/init script generates a .env file containing the variables as passed as per normal Huginn documentation.
The same environment variables that would be used for Heroku PaaS deployment are used by this script.

The scripts/init script is aware of mysql and postgres linked containers through the environment variables:

    MYSQL_PORT_3306_TCP_ADDR
    MYSQL_PORT_3306_TCP_PORT

and

    POSTGRES_PORT_5432_TCP_ADDR
    POSTGRES_PORT_5432_TCP_PORT

Its recommended to use an image that allows you to create a database via environmental variables at docker run, like `postgresql` or `mysql`, so the db is populated when this script runs.

Additionally, the database variables may be overridden from the above as per the standard Huginn documentation:

    DATABASE_ADAPTER #(must be either 'postgresql' or 'mysql2')
    DATABASE_HOST
    DATABASE_PORT

If your database user does not have the permission to create the Huginn database please make sure it exists and set the `DO_NOT_CREATE_DATABASE` environment variable.

This script will run database migrations (rake db:migrate) which should be idempotent.

It will also seed the database (rake db:seed) unless this is defined:

    DO_NOT_SEED

This same seeding initially defines the "admin" user with a default password of "password" as per the standard Huginn documentation.

If you do not wish to have the default 6 agents, you will want to set the above environment variable after your initially deploy, otherwise they will be added automatically the next time a container pointing at the database is spun up.

The CMD launches Huginn via the scripts/init script. This may become the ENTRYPOINT later.  It does take under a minute for Huginn to come up.  Use environmental variables that match your DB's creds to ensure it works.

## Usage

Simple startup using docker compose (you need to daemonize with `-d` to persist the data):

    cd docker/single-process
    docker-compose up

or if you like to use PostgreSQL:

    docker-compose -f postgresql.yml up

Manual startup and linking to a MySQL container:

    docker run --name huginn_mysql \
        -e MYSQL_DATABASE=huginn \
        -e MYSQL_USER=huginn \
        -e MYSQL_PASSWORD=somethingsecret \
        -e MYSQL_ROOT_PASSWORD=somethingevenmoresecret \
        mysql

    docker run --name huginn_web \
        --link huginn_mysql:mysql \
        -p 3000:3000 \
        -e DATABASE_NAME=huginn \
        -e DATABASE_USERNAME=huginn \
        -e DATABASE_PASSWORD=somethingsecret \
        huginn/huginn-single-process

    docker run --name huginn_threaded \
        --link huginn_mysql:mysql \
        -e DATABASE_NAME=huginn \
        -e DATABASE_USERNAME=huginn \
        -e DATABASE_PASSWORD=somethingsecret \
        huginn/huginn-single-process /scripts/init bin/threaded.rb

## Environment Variables

Other Huginn [12factored](https://12factor.net/) environment variables of note are generated and put into the .env file as per Huginn documentation. All variables of the [.env.example](https://github.com/huginn/huginn/blob/master/.env.example) can be used to override the defaults which a read from the current `.env.example`.

For variables in the .env.example that are commented out, the default is to not include that variable in the generated .env file.

In newer versions of Docker you are able to pass your own .env file in to the container with the `--env-file` parameter.

## Building on your own

You don't need to do this on your own, but if you really want run this command in the Huginn root directory:

    docker build --rm=true --tag={yourname}/huginn -f docker/single-process/Dockerfile .

## Source

The source is [available on GitHub](https://github.com/huginn/huginn/docker/single-process/).

Please feel free to submit pull requests and/or fork at your leisure.


text:
package com.evojam.driver

import org.bson.Document

trait DocumentFormat[A] {
  def writes(a: A): Document
  def reads(doc: Document): A
}

object DocumentFormat {
  def writes[A](a: A)(implicit fmt: DocumentFormat[A]) = fmt.writes(a)
  def reads[A](doc: Document)(implicit fmt: DocumentFormat[A]) = fmt.reads(doc)
}


text:
import React from 'react';
import { history } from 'react-router/lib/HashHistory';
import { Router, Route, Link, Navigation } from 'react-router';
import { loadContacts, loadContact, createContact } from './utils';
import AsyncProps from 'react-router/lib/experimental/AsyncProps';

var Spinner = React.createClass({
  render() {
    return (

    );
  }
});

var App = React.createClass({
  mixins: [ Navigation ],

  getDefaultProps() {
    return { contacts: [] };
  },

  statics: {
    loadProps(params, cb) {
      loadContacts(cb);
    }
  },

  handleSubmit(event) {
    event.preventDefault();
    createContact({
      first: event.target.elements[0].value,
      last: event.target.elements[1].value
    }, (err, data) => {
      this.props.reloadAsyncProps();
      this.transitionTo(`/contact/${data.contact.id}`);
    });
    event.target.reset();
    event.target.elements[0].focus();
  },

  render() {
    // super smooth user feedback
    var appStyle = {
      transition: this.props.loading ? 'opacity 500ms ease 250ms' : 'opacity 150ms',
      opacity: this.props.loading ? 0.5 : 1
    };

    return (

        <form onSubmit={this.handleSubmit}>
          <input placeholder="First name"/> <input placeholder="Last name"/>{' '}
          <button type="submit">submit</button>
        </form>

            {this.props.contacts.map((contact, i) => (

                <Link to={`/contact/${contact.id}`}>{contact.first} {contact.last}</Link>

            ))}

            {this.props.children}

    );
  }
});

var Contact = React.createClass({

  getDefaultProps() {
    return { contact: {} };
  },

  statics: {
    loadProps(params, cb) {
      loadContact(params.id, cb);
    }
  },

  render() {
    var { contact } = this.props;

    return (

<Link to="/">Back</Link>

{contact.first} {contact.last}

    );
  }
});

var Index = React.createClass({
  render() {
    return (

Welcome!

    );
  }
});

React.render((
  <Router history={history} createElement={AsyncProps.createElement}>
    <Route component={AsyncProps} renderInitialLoad={() => <Spinner/> }>
      <Route component={App}>
        <Route path="/" component={Index}/>
        <Route path="contact/:id" component={Contact}/>
      </Route>
    </Route>
  </Router>
), document.getElementById('example'));


text:
<?php

namespace Controller;

use Silex\Application;

abstract class ControllerAbstract
{
    // L apropriété $app va contenir notre appli $app est un objet de la classe Apllication
    protected $app;

    // La propriété va contenir un accès direct à twig, c'est un objet de la classe \Twig_Environment
    protected $twig;

    // On redéfinit une propriété private $session qui sera passée dans le constructeur pour déclencher une session utilisateur
    /**
     *
     * @var \Symfony\Component\HttpFoundation\Session\Session
     */
    protected $session;

    public function __construct(Application $app)
    {
        $this->app = $app;
        $this->twig = $app['twig'];
        //
        $this->session = $app['session'];
    }

    /**
     *
     * @param string $view
     * @param array $parameters
     * return string
     */
    // Obliger de déclarer les prameters sous forme d'array
    public function render($view, array $parameters = [])
    {
        return $this->twig->render($view, $parameters);
    }

    /**
     *
     * @param string $routeName
     * @param array $parameters, pour les id ou toute variable que l'on passe dans l'URL
     *  (voir slug, lissage d'URL, on remplace les caractères spéciaux et les expaces par des tirets ou on optimise le référencement=
     * @return \Symphony\Component\HttpFoundation\RedirecteResponse
     */
    public function redirectRoute($routeName, array $parameters = [])
    {
        return $this->app->redirect(
            $this->app['url_generator']->generate($routeName, $parameters)
         );

    }

    // $type définit si c'est un message de succès, on aurait pu mettre erreur
    public function addFlashMessage($message, $type = 'success')
    {
        // getFlashBag() est prédéfini dans Symphony
        $this->session->getFlashBag()->add($type, $message);
    }

}


text:
package org.axonframework.disruptor.commandhandling;

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.LifecycleAware;
import org.axonframework.common.Assert;
import org.axonframework.common.caching.Cache;
import org.axonframework.eventsourcing.AggregateCacheEntry;
import org.axonframework.eventsourcing.AggregateFactory;
import org.axonframework.eventsourcing.EventSourcedAggregate;
import org.axonframework.eventsourcing.SnapshotTrigger;
import org.axonframework.eventsourcing.SnapshotTriggerDefinition;
import org.axonframework.eventsourcing.eventstore.DomainEventStream;
import org.axonframework.eventsourcing.eventstore.EventStore;
import org.axonframework.messaging.Message;
import org.axonframework.messaging.ScopeDescriptor;
import org.axonframework.messaging.annotation.ClasspathHandlerDefinition;
import org.axonframework.messaging.annotation.HandlerDefinition;
import org.axonframework.messaging.annotation.ParameterResolverFactory;
import org.axonframework.messaging.unitofwork.CurrentUnitOfWork;
import org.axonframework.modelling.command.Aggregate;
import org.axonframework.modelling.command.AggregateNotFoundException;
import org.axonframework.modelling.command.AggregateScopeDescriptor;
import org.axonframework.modelling.command.ConflictingAggregateVersionException;
import org.axonframework.modelling.command.Repository;
import org.axonframework.modelling.command.RepositoryProvider;
import org.axonframework.modelling.command.inspection.AggregateModel;
import org.axonframework.modelling.command.inspection.AnnotatedAggregateMetaModelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

import static org.axonframework.commandhandling.GenericCommandResultMessage.asCommandResultMessage;

/**
 * Component of the DisruptorCommandBus that invokes the command handler. The execution is done within a Unit Of Work.
 * If an aggregate has been pre-loaded, it is set to the ThreadLocal.
 *
 * @author Allard Buijze
 * @since 2.0
 */
public class CommandHandlerInvoker implements EventHandler<CommandHandlingEntry>, LifecycleAware {

    private static final Logger logger = LoggerFactory.getLogger(CommandHandlerInvoker.class);
    private static final ThreadLocal<CommandHandlerInvoker> CURRENT_INVOKER = new ThreadLocal<>();

    private final Map<Class<?>, DisruptorRepository> repositories = new ConcurrentHashMap<>();
    private final Cache cache;
    private final int segmentId;

    /**
     * Returns the Repository instance for Aggregate with given {@code typeIdentifier} used by the
     * CommandHandlerInvoker that is running on the current thread.
     * <p>
     * Calling this method from any other thread will return {@code null}.
     *
     * @param type The type of aggregate
     * @param <T>  The type of aggregate
     * @return the repository instance for aggregate of given type
     */
    @SuppressWarnings("unchecked")
    public static <T> DisruptorRepository<T> getRepository(Class<?> type) {
        final CommandHandlerInvoker invoker = CURRENT_INVOKER.get();
        Assert.state(invoker != null,
                     () -> "The repositories of a DisruptorCommandBus are only available " + "in the invoker thread");
        return invoker.repositories.get(type);
    }

    /**
     * Create an aggregate invoker instance for the given {@code segment} and {@code cache}.
     *
     * @param cache     The cache temporarily storing aggregate instances
     * @param segmentId The id of the segment this invoker should handle
     */
    public CommandHandlerInvoker(Cache cache, int segmentId) {
        this.cache = cache;
        this.segmentId = segmentId;
    }

    @Override
    public void onEvent(CommandHandlingEntry entry, long sequence, boolean endOfBatch) {
        if (entry.isRecoverEntry()) {
            removeEntry(entry.getAggregateIdentifier());
        } else if (entry.getInvokerId() == segmentId) {
            entry.start();
            try {
                Object result = entry.getInvocationInterceptorChain().proceed();
                entry.setResult(asCommandResultMessage(result));
            } catch (Exception throwable) {
                entry.setResult(asCommandResultMessage(throwable));
            } finally {
                entry.pause();
            }
        }
    }

    /**
     * Create a repository instance for an aggregate created by the given {@code aggregateFactory}. The returning
     * repository must be safe to use by this invoker instance.
     *
     * @param <T>                       The type of aggregate created by the factory
     * @param eventStore                The events store to load and publish events
     * @param aggregateFactory          The factory creating aggregate instances
     * @param snapshotTriggerDefinition The trigger definition for snapshots
     * @param parameterResolverFactory  The factory used to resolve parameters on command handler methods
     * @return A Repository instance for the given aggregate
     */
    @SuppressWarnings("unchecked")
    public <T> Repository<T> createRepository(EventStore eventStore,
                                              AggregateFactory<T> aggregateFactory,
                                              SnapshotTriggerDefinition snapshotTriggerDefinition,
                                              ParameterResolverFactory parameterResolverFactory) {
        return createRepository(eventStore,
                                null,
                                aggregateFactory,
                                snapshotTriggerDefinition,
                                parameterResolverFactory,
                                ClasspathHandlerDefinition.forClass(aggregateFactory.getAggregateType()));
    }

    /**
     * Create a repository instance for an aggregate created by the given {@code aggregateFactory}. The returning
     * repository must be safe to use by this invoker instance.
     *
     * @param <T>                       The type of aggregate created by the factory
     * @param eventStore                The events store to load and publish events
     * @param repositoryProvider        Provides repositories for specified aggregate types
     * @param aggregateFactory          The factory creating aggregate instances
     * @param snapshotTriggerDefinition The trigger definition for snapshots
     * @param parameterResolverFactory  The factory used to resolve parameters on command handler methods
     * @param handlerDefinition         The handler definition used to create concrete handlers
     * @return A Repository instance for the given aggregate
     */
    @SuppressWarnings("unchecked")
    public <T> Repository<T> createRepository(EventStore eventStore,
                                              RepositoryProvider repositoryProvider,
                                              AggregateFactory<T> aggregateFactory,
                                              SnapshotTriggerDefinition snapshotTriggerDefinition,
                                              ParameterResolverFactory parameterResolverFactory,
                                              HandlerDefinition handlerDefinition) {
        return repositories.computeIfAbsent(
                aggregateFactory.getAggregateType(),
                k -> new DisruptorRepository<>(
                        aggregateFactory,
                        cache,
                        eventStore,
                        parameterResolverFactory,
                        handlerDefinition,
                        snapshotTriggerDefinition,
                        repositoryProvider
                ));
    }

    private void removeEntry(String aggregateIdentifier) {
        for (DisruptorRepository repository : repositories.values()) {
            repository.removeFromCache(aggregateIdentifier);
        }
        cache.remove(aggregateIdentifier);
    }

    @Override
    public void onStart() {
        CURRENT_INVOKER.set(this);
    }

    @Override
    public void onShutdown() {
        CURRENT_INVOKER.remove();
    }

    /**
     * Repository implementation that is safe to use by a single CommandHandlerInvoker instance.
     *
     * @param <T> The type of aggregate stored in this repository
     */
    static final class DisruptorRepository<T> implements Repository<T> {

        private final EventStore eventStore;
        private final RepositoryProvider repositoryProvider;
        private final SnapshotTriggerDefinition snapshotTriggerDefinition;
        private final AggregateFactory<T> aggregateFactory;
        private final FirstLevelCache<T> firstLevelCache = new FirstLevelCache<>();
        private final Cache cache;
        private final AggregateModel<T> model;

        private DisruptorRepository(AggregateFactory<T> aggregateFactory,
                                    Cache cache,
                                    EventStore eventStore,
                                    ParameterResolverFactory parameterResolverFactory,
                                    SnapshotTriggerDefinition snapshotTriggerDefinition,
                                    RepositoryProvider repositoryProvider) {
            this.aggregateFactory = aggregateFactory;
            this.cache = cache;
            this.eventStore = eventStore;
            this.snapshotTriggerDefinition = snapshotTriggerDefinition;
            this.model = AnnotatedAggregateMetaModelFactory.inspectAggregate(aggregateFactory.getAggregateType(),
                                                                             parameterResolverFactory);
            this.repositoryProvider = repositoryProvider;
        }

        private DisruptorRepository(AggregateFactory<T> aggregateFactory, Cache cache, EventStore eventStore,
                                    ParameterResolverFactory parameterResolverFactory,
                                    HandlerDefinition handlerDefinition,
                                    SnapshotTriggerDefinition snapshotTriggerDefinition,
                                    RepositoryProvider repositoryProvider) {
            this.aggregateFactory = aggregateFactory;
            this.cache = cache;
            this.eventStore = eventStore;
            this.snapshotTriggerDefinition = snapshotTriggerDefinition;
            this.model = AnnotatedAggregateMetaModelFactory.inspectAggregate(aggregateFactory.getAggregateType(),
                                                                             parameterResolverFactory,
                                                                             handlerDefinition);
            this.repositoryProvider = repositoryProvider;
        }

        @Override
        public Aggregate<T> load(String aggregateIdentifier, Long expectedVersion) {
            ((CommandHandlingEntry) CurrentUnitOfWork.get()).registerAggregateIdentifier(aggregateIdentifier);
            Aggregate<T> aggregate = load(aggregateIdentifier);
            if (expectedVersion != null && aggregate.version() > expectedVersion) {
                throw new ConflictingAggregateVersionException(aggregateIdentifier, expectedVersion,
                                                               aggregate.version());
            }
            return aggregate;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Aggregate<T> load(String aggregateIdentifier) {
            ((CommandHandlingEntry) CurrentUnitOfWork.get()).registerAggregateIdentifier(aggregateIdentifier);
            EventSourcedAggregate<T> aggregateRoot = firstLevelCache.get(aggregateIdentifier);
            if (aggregateRoot == null) {
                Object cachedItem = cache.get(aggregateIdentifier);
                if (AggregateCacheEntry.class.isInstance(cachedItem)) {
                    EventSourcedAggregate<T> cachedAggregate = ((AggregateCacheEntry<T>) cachedItem).recreateAggregate(
                            model, eventStore, repositoryProvider, snapshotTriggerDefinition
                    );

                    aggregateRoot = cachedAggregate.invoke(r -> {
                        if (aggregateFactory.getAggregateType().isInstance(r)) {
                            return cachedAggregate;
                        } else {
                            return null;
                        }
                    });
                }
            }
            if (aggregateRoot == null) {
                logger.debug("Aggregate {} not in first level cache, loading fresh one from Event Store",
                             aggregateIdentifier);
                DomainEventStream eventStream = eventStore.readEvents(aggregateIdentifier);
                SnapshotTrigger trigger = snapshotTriggerDefinition.prepareTrigger(aggregateFactory.getAggregateType());
                if (!eventStream.hasNext()) {
                    throw new AggregateNotFoundException(aggregateIdentifier,
                                                         "The aggregate was not found in the event store");
                }
                aggregateRoot = EventSourcedAggregate.initialize(aggregateFactory.createAggregateRoot(
                        aggregateIdentifier, eventStream.peek()), model, eventStore, repositoryProvider, trigger
                );

                aggregateRoot.initializeState(eventStream);
                firstLevelCache.put(aggregateRoot.identifierAsString(), aggregateRoot);
                cache.put(aggregateIdentifier, new AggregateCacheEntry<>(aggregateRoot));
            }
            return aggregateRoot;
        }

        @Override
        public Aggregate<T> newInstance(Callable<T> factoryMethod) throws Exception {
            SnapshotTrigger trigger = snapshotTriggerDefinition.prepareTrigger(aggregateFactory.getAggregateType());
            EventSourcedAggregate<T> aggregate = EventSourcedAggregate.initialize(factoryMethod,
                                                                                model,
                                                                                eventStore,
                                                                                repositoryProvider,
                                                                                trigger);
            firstLevelCache.put(aggregate.identifierAsString(), aggregate);
            cache.put(aggregate.identifierAsString(), new AggregateCacheEntry<>(aggregate));
            return aggregate;
        }

        private void removeFromCache(String aggregateIdentifier) {
            EventSourcedAggregate<T> removed = firstLevelCache.remove(aggregateIdentifier);
            if (removed != null) {
                logger.debug("Aggregate {} removed from first level cache for recovery purposes.",
                    aggregateIdentifier);
            }
        }

        @Override
        public void send(Message<?> message, ScopeDescriptor scopeDescription) throws Exception {
            if (canResolve(scopeDescription)) {
                String aggregateIdentifier = ((AggregateScopeDescriptor) scopeDescription).getIdentifier().toString();
                load(aggregateIdentifier).handle(message);
            }
        }

        @Override
        public boolean canResolve(ScopeDescriptor scopeDescription) {
            return scopeDescription instanceof AggregateScopeDescriptor
                    && Objects.equals(model.type(), ((AggregateScopeDescriptor) scopeDescription).getType());
        }
    }
}


text: echo "Connected at 999985"


text:
import React, { Component } from 'react';

export type InputModeTypes =
    'verbatim' | 'latin' | 'latin-name' | 'latin-prose' |
    'full-width-latin' | 'kana' | 'kana-name' | 'katakana' |
    'numeric' | 'tel' | 'email' | 'url'

export interface ReactCodeInputProps {

    // Type of input accept
    type?: 'text' | 'number' | 'password' | 'tel'

    // Allowed amount of characters to enter.
    fields?: number

    // Placeholder of the inputs.
    placeholder?: string

    // Value of the input
    value?: string

    // Get the full value of the input on every change
    onChange?: (value: string) => void

    // Setting the name of component.
    name: string

    // Marks the given fields as "touched" to show errors.
    touch?: (name: string) => void

    // Clears the "touched" flag for the given fields.
    untouch?: (name: string) => void

    // Add classname to the root element.
    className?: string

    isValid?: boolean

    // When present, it specifies that the element should be disabled.
    disabled?: boolean

    // Setting the styles of container element.
    style?: React.CSSProperties

    // Setting the styles of each input field.
    inputStyle?: React.CSSProperties

    // Setting the styles of each input field if isValid prop is false.
    inputStyleInvalid?: React.CSSProperties

    // Setup autofocus on the first input, true by default.
    autoFocus?: boolean

    //
    forceUppercase?: boolean

    // Filter characters on key down.
    filterKeyCodes?: Array<number>

    // Filter characters.
    filterChars?: Array<string>

    // Filter above acts as blacklist if false, whitelist if true; false by default.
    filterCharsIsWhitelist?: boolean;

    // The pattern prop specifies a regular expression that the element's value is checked against.
    pattern?: string

    // The inputMode prop tells the browser on devices with dynamic keyboards which keyboard to display.
    inputMode: InputModeTypes

}

declare class ReactCodeInput extends Component<ReactCodeInputProps, any> {
    constructor(props: ReactCodeInputProps);
}

export default ReactCodeInput


text:
module.exports = function(grunt) {
  "use strict";

  // load all grunt tasks in package.json with load-grunt-tasks task :)
  require('load-grunt-tasks')(grunt);

  grunt.initConfig({
    compass: {
      dist: {
        options: {
          config: 'src/editor-style/config.rb',
          sassDir: 'src/editor-style/sass',
          cssDir: 'build/'
        }
      }
    },
    watch: {
      editor: {
        files: ['src/*', 'src/**/*'],
        tasks: ["default"]
      }
    }
  });

  grunt.registerTask("default", ["compass"]);
};


text:
/**
 */
package gluemodel.CIM.IEC61970.OperationalLimits;

/**
 *
 * A representation of the model object 'Voltage Limit'.
 *
 *
 *

 * The following features are supported:
 *

 *

 *
{@link gluemodel.CIM.IEC61970.OperationalLimits.VoltageLimit#getValue Value}

 *

 *
 * @see gluemodel.CIM.IEC61970.OperationalLimits.OperationalLimitsPackage#getVoltageLimit()
 * @model annotation="http://iec.ch/TC57/2009/CIM-schema-cim14 Documentation='Operational limit applied to voltage.'"
 *        annotation="http://langdale.com.au/2005/UML Profile\040documentation='Operational limit applied to voltage.'"
 *        annotation="http://www.eclipse.org/emf/2002/GenModel Documentation='Operational limit applied to voltage.' Profile\040documentation='Operational limit applied to voltage.'"
 * @generated
 */
public interface VoltageLimit extends OperationalLimit {
	/**
	 * Returns the value of the 'Value' attribute.
	 *
	 *

	 * If the meaning of the 'Value' attribute isn't clear,
	 * there really should be more of a description here...
	 *

	 *
	 * @return the value of the 'Value' attribute.
	 * @see #setValue(float)
	 * @see gluemodel.CIM.IEC61970.OperationalLimits.OperationalLimitsPackage#getVoltageLimit_Value()
	 * @model dataType="gluemodel.CIM.IEC61970.Domain.Voltage" required="true"
	 *        annotation="http://iec.ch/TC57/2009/CIM-schema-cim14 Documentation='Limit on voltage. High or low limit depends on the OperatoinalLimit.limitKind'"
	 *        annotation="http://www.eclipse.org/emf/2002/GenModel Documentation='Limit on voltage. High or low limit depends on the OperatoinalLimit.limitKind'"
	 * @generated
	 */
	float getValue();

	/**
	 * Sets the value of the '{@link gluemodel.CIM.IEC61970.OperationalLimits.VoltageLimit#getValue Value}' attribute.
	 *
	 *
	 * @param value the new value of the 'Value' attribute.
	 * @see #getValue()
	 * @generated
	 */
	void setValue(float value);

} // VoltageLimit


text:
/**
 * Helper class that closes components
 */
export declare class Closer {
    /**
     * Closes a component that implement ICloseable interface
     * @param correlationId a unique transaction id to trace calls across components
     * @param component a components to be closed
     * @param callback a function to call back when close is complete
     */
    static closeOne(correlationId: string, component: any, callback?: (err: any) => void): void;
    /**
     * Closes components that implement ICloseable interface
     * @param correlationId a unique transaction id to trace calls across components
     * @param components a list of components to be closed
     * @param callback a function to call back when cleaning is complete
     */
    static close(correlationId: string, components: any[], callback?: (err: any) => void): void;
}


text:
using System.Collections.Generic;

namespace GraphLib.EdgeKeeping
{
    internal class FakeEdgeKeeper : IEdgeKeeper
    {
        public void Add(Edge edge)
        {

        }

        public void Remove(Edge edge)
        {

        }

        public IEnumerable<Edge> GetEdges()
        {
            return null;
        }
    }
}


text:
@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) UITabBarController *tabBarController;

@end


text:
import test from 'ava';
import sinon from 'sinon';
import { playNote } from '../playNote';

test('should invoke triggerAttackRelease method on instrument with name, length, time', t => {
  const expected = ['C3', '(8 * 32n)', '(0 * 32n)'];
  const triggerAttackRelease = sinon.spy();
  playNote({ triggerAttackRelease }, 'C3', '(8 * 32n)', '(0 * 32n)');
  const result = triggerAttackRelease.lastCall.args;
  t.deepEqual(result, expected);
});

test('should use "16n" as value for length when length is not defined', t => {
  const expected = ['C3', '16n', undefined];
  const triggerAttackRelease = sinon.spy();
  playNote({ triggerAttackRelease }, 'C3');
  const result = triggerAttackRelease.lastCall.args;
  t.deepEqual(result, expected);
});


text:
package com.mars.shiro.guice.resteasy.webapp.archetype.servlet.modules;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
import com.mars.shiro.guice.resteasy.webapp.archetype.servlet.config.GenericBootstrapConstants;
/**
 * Guice Module to load Properties file and bind it to Guice Injector.

 * Properties can later be used in constructor or field injection by using:

 * @Inject @Named("name.of.the.key") private String propValue;
 *
 * @author pablo.biagioli
 *
 */
public class BootstrapPropertiesModule extends AbstractModule{

	@Override
	protected void configure() {
		Properties bootstrapProperties = new Properties();
		try {
			InputStream is = getClass().getResourceAsStream("/"+GenericBootstrapConstants.BOOTSTRAP_PROPERTIES_FILE);
			bootstrapProperties.load(is);
			Names.bindProperties(binder(), bootstrapProperties);
		} catch (FileNotFoundException e) {
	        System.out.println("The configuration file "+ GenericBootstrapConstants.BOOTSTRAP_PROPERTIES_FILE + " can not be found");
	    } catch (IOException e) {
	        System.out.println("I/O Exception during loading configuration");
	    }
	}

}


text:
import os

import testtools
from mock import patch

from cloudify import decorators
from cloudify import exceptions
from cloudify import logs
from cloudify.workflows import local

@decorators.operation
def op(ctx, retry_type, **_):
    if 0 <= ctx.operation.max_retries <= ctx.operation.retry_number:
        return
    if retry_type == 'retry':
        ctx.operation.retry()
    elif retry_type == 'error':
        raise RuntimeError()
    elif retry_type == 'non-recoverable':
        raise exceptions.NonRecoverableError()

@decorators.workflow
def execute_operation(ctx, retry_type, **_):
    instance = next(next(ctx.nodes).instances)
    instance.execute_operation('test.op', kwargs={
        'retry_type': retry_type,
    })

class TaskRetryEventContextTests(testtools.TestCase):

    def setUp(self):
        blueprint_path = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            "resources/blueprints/"
            "test-task-retry-event-context-blueprint.yaml")
        self.env = local.init_env(blueprint_path)
        super(TaskRetryEventContextTests, self).setUp()

    def test_operation_retry(self):
        self._test_impl('retry', task_retries=2)

    def test_recoverable_retry(self):
        self._test_impl('error', task_retries=2)

    def test_infinite_retries(self):
        self._test_impl('non-recoverable', task_retries=-1)

    def _test_impl(self, retry_type, task_retries):
        events = []
        original_event_out = logs.stdout_event_out

        def event_output(event):
            original_event_out(event)
            events.append(event)
        with patch('cloudify.logs.stdout_event_out', event_output):
            try:
                self.env.execute('execute_operation',
                                 task_retries=task_retries,
                                 task_retry_interval=0,
                                 parameters={
                                     'retry_type': retry_type
                                 })
            except exceptions.NonRecoverableError:
                pass
        events = [e for e in events if
                  e.get('event_type', '').startswith('task_') or
                  e.get('event_type', '').startswith('sending_task')]
        range_size = task_retries if task_retries > 0 else 1
        for i in range(range_size):
            # The following assertions are mostly here for sanity.
            # we generally want to make sure all task event contain
            # current_retries and total_retries so all tests try to go though
            # all event types.
            self.assertEqual('sending_task', events[i*3 + 0]['event_type'])
            self.assertEqual('task_started', events[i*3 + 1]['event_type'])
            if retry_type == 'retry':
                if i < task_retries:
                    expected_type = 'task_rescheduled'
                else:
                    expected_type = 'task_succeeded'
            elif retry_type == 'error':
                if i < task_retries:
                    expected_type = 'task_failed'
                else:
                    expected_type = 'task_succeeded'
            elif retry_type == 'non-recoverable':
                expected_type = 'task_failed'
            else:
                raise RuntimeError('We should not have arrived here')
            self.assertEqual(expected_type, events[i*3 + 2]['event_type'])

            # The following are the actual test assertions
            for j in range(3):
                context = events[i*3 + j]['context']
                self.assertEqual(i, context['task_current_retries'])
                self.assertEqual(task_retries, context['task_total_retries'])


text:
// - Import react components
import _ from 'lodash'
import { Map } from 'immutable'

// - Import action types
import { ServerActionType } from 'constants/serverActionType'

// Import domain

import { ServerState } from './ServerState'
import { IServerAction } from './IServerAction'
import { ServerRequestModel } from 'src/models/server/serverRequestModel'
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'

/**
 * Server actions
 * @param {object} state
 * @param {object} action
 */
export let serverReducer = (state = Map(new ServerState()), action: IServerAction) => {
  let { payload } = action
  const request = (payload ? payload.request : {}) as ServerRequestModel
  switch (action.type) {

    /* _____________ CRUD _____________ */
    case ServerActionType.ADD_REQUEST:
      return state
        .setIn(['request', request.id], request)

    case ServerActionType.DELETE_REQUEST:
      return state
        .deleteIn(['request', request.id])

    case ServerActionType.ERROR_REQUEST:
      return state
        .setIn(['request', request.id, 'status'], ServerRequestStatusType.Error)

    case ServerActionType.OK_REQUEST:
      return state
        .setIn(['request', request.id, 'status'], ServerRequestStatusType.OK)

    case ServerActionType.CLEAR_ALL_DATA_REQUEST:
      return Map(new ServerState())

    default:
      return state
  }
}


text:
require 'fog/core/model'

module Fog
  module Brightbox
    class Compute

      class LoadBalancer < Fog::Model

        identity :id

        attribute :url
        attribute :name
        attribute :status
        attribute :resource_type

        attribute :nodes
        attribute :policy
        attribute :healthcheck
        attribute :listeners
        attribute :account

        def ready?
          status == 'active'
        end

        def save
          requires :nodes, :listeners, :healthcheck
          options = {
            :nodes => nodes,
            :listeners => listeners,
            :healthcheck => healthcheck,
            :policy => policy,
            :name => name
          }.delete_if {|k,v| v.nil? || v == "" }
          data = connection.create_load_balancer(options)
          merge_attributes(data)
          true
        end

        def destroy
          requires :identity
          connection.destroy_load_balancer(identity)
          true
        end

      end

    end
  end
end


text:
package bio.terra.workspace.app.controller;

import static bio.terra.workspace.common.fixtures.WorkspaceFixtures.SHORT_DESCRIPTION_PROPERTY;
import static bio.terra.workspace.common.fixtures.WorkspaceFixtures.TYPE_PROPERTY;
import static bio.terra.workspace.common.fixtures.WorkspaceFixtures.VERSION_PROPERTY;
import static bio.terra.workspace.common.utils.MockMvcUtils.UPDATE_WORKSPACES_V1_POLICIES_PATH_FORMAT;
import static bio.terra.workspace.common.utils.MockMvcUtils.UPDATE_WORKSPACES_V1_PROPERTIES_PATH_FORMAT;
import static bio.terra.workspace.common.utils.MockMvcUtils.USER_REQUEST;
import static bio.terra.workspace.common.utils.MockMvcUtils.WORKSPACES_V1_PATH;
import static bio.terra.workspace.common.utils.MockMvcUtils.addAuth;
import static bio.terra.workspace.common.utils.MockMvcUtils.addJsonContentType;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import bio.terra.workspace.common.BaseUnitTestMockDataRepoService;
import bio.terra.workspace.common.utils.MockMvcUtils;
import bio.terra.workspace.db.WorkspaceActivityLogDao;
import bio.terra.workspace.generated.model.ApiCloneResourceResult;
import bio.terra.workspace.generated.model.ApiCloneWorkspaceResult;
import bio.terra.workspace.generated.model.ApiCloningInstructionsEnum;
import bio.terra.workspace.generated.model.ApiCreateDataRepoSnapshotReferenceRequestBody;
import bio.terra.workspace.generated.model.ApiCreatedWorkspace;
import bio.terra.workspace.generated.model.ApiDataRepoSnapshotAttributes;
import bio.terra.workspace.generated.model.ApiDataRepoSnapshotResource;
import bio.terra.workspace.generated.model.ApiErrorReport;
import bio.terra.workspace.generated.model.ApiProperties;
import bio.terra.workspace.generated.model.ApiProperty;
import bio.terra.workspace.generated.model.ApiPropertyKeys;
import bio.terra.workspace.generated.model.ApiReferenceResourceCommonFields;
import bio.terra.workspace.generated.model.ApiResourceCloneDetails;
import bio.terra.workspace.generated.model.ApiTpsComponent;
import bio.terra.workspace.generated.model.ApiTpsObjectType;
import bio.terra.workspace.generated.model.ApiTpsPaoGetResult;
import bio.terra.workspace.generated.model.ApiTpsPaoUpdateRequest;
import bio.terra.workspace.generated.model.ApiTpsPaoUpdateResult;
import bio.terra.workspace.generated.model.ApiTpsPolicyInput;
import bio.terra.workspace.generated.model.ApiTpsPolicyInputs;
import bio.terra.workspace.generated.model.ApiTpsPolicyPair;
import bio.terra.workspace.generated.model.ApiTpsUpdateMode;
import bio.terra.workspace.generated.model.ApiWorkspaceDescription;
import bio.terra.workspace.generated.model.ApiWorkspaceDescriptionList;
import bio.terra.workspace.generated.model.ApiWorkspaceStageModel;
import bio.terra.workspace.service.iam.model.SamConstants;
import bio.terra.workspace.service.iam.model.SamConstants.SamResource;
import bio.terra.workspace.service.iam.model.SamConstants.SamSpendProfileAction;
import bio.terra.workspace.service.iam.model.WsmIamRole;
import bio.terra.workspace.service.workspace.model.WorkspaceConstants.Properties;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import java.time.OffsetDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.HttpStatus;
import org.broadinstitute.dsde.workbench.client.sam.model.UserStatusInfo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

/**
 * An example of a mockMvc-based unit test for a controller.
 *
 * <p>In general, we would like to move towards testing new endpoints via controller instead of
 * calling services directly like we have in the past. Although this test duplicates coverage
 * currently in WorkspaceServiceTest, it's intended as a proof-of-concept for future mockMvc-based
 * tests.
 */
public class WorkspaceApiControllerTest extends BaseUnitTestMockDataRepoService {
  /** A fake group-constraint policy for a workspace. */
  private static final ApiTpsPolicyInput GROUP_POLICY =
      new ApiTpsPolicyInput()
          .namespace("terra")
          .name("group-constraint")
          .addAdditionalDataItem(new ApiTpsPolicyPair().key("group").value("my_fake_group"));

  private static final String FAKE_SPEND_PROFILE = "fake-spend-profile";

  @Autowired MockMvc mockMvc;
  @Autowired MockMvcUtils mockMvcUtils;
  @Autowired ObjectMapper objectMapper;
  @Autowired WorkspaceActivityLogDao workspaceActivityLogDao;

  private static ApiTpsPaoGetResult emptyWorkspacePao() {
    return new ApiTpsPaoGetResult()
        .component(ApiTpsComponent.WSM)
        .objectType(ApiTpsObjectType.WORKSPACE)
        .objectId(UUID.randomUUID())
        .sourcesObjectIds(Collections.emptyList())
        .attributes(new ApiTpsPolicyInputs())
        .effectiveAttributes(new ApiTpsPolicyInputs());
  }

  @BeforeEach
  public void setup() throws InterruptedException {
    when(mockSamService()
            .isAuthorized(
                any(), eq(SamResource.SPEND_PROFILE), any(), eq(SamSpendProfileAction.LINK)))
        .thenReturn(true);
    when(mockSamService().listRequesterRoles(any(), any(), any()))
        .thenReturn(List.of(WsmIamRole.OWNER));
    when(mockSamService().getUserStatusInfo(any()))
        .thenReturn(
            new UserStatusInfo()
                .userEmail(USER_REQUEST.getEmail())
                .userSubjectId(USER_REQUEST.getSubjectId()));
    when(mockSamService().isAuthorized(any(), eq(SamConstants.SamResource.WORKSPACE), any(), any()))
        .thenReturn(true);

    when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(true);
    // We don't need to mock tpsCheck() because Mockito will already do nothing by default.

    // Pretend every workspace has an empty policy. The ID on the PAO will not match the workspace
    // ID, but that doesn't matter for tests which don't care about policy.
    when(mockTpsApiDispatch().getPaoIfExists(any(), any()))
        .thenReturn(Optional.of(emptyWorkspacePao()));
  }

  @Test
  public void createWorkspace_duplicateUuid_throws409() throws Exception {
    UUID workspaceId = UUID.randomUUID();
    mockMvcUtils.createWorkspaceWithoutCloudContextExpectError(
        USER_REQUEST, workspaceId, /*stageModel=*/ null, /*policies=*/ null, HttpStatus.SC_OK);
    mockMvcUtils.createWorkspaceWithoutCloudContextExpectError(
        USER_REQUEST,
        workspaceId,
        /*stageModel=*/ null,
        /*policies=*/ null,
        HttpStatus.SC_CONFLICT);
  }

  @Test
  public void createWorkspace_policyRejectedForRawlsWorkspace_throws400() throws Exception {
    ApiErrorReport errorReport =
        createRawlsWorkspaceWithPolicyExpectError(HttpStatus.SC_BAD_REQUEST);
    assertTrue(
        errorReport.getMessage().contains(ApiWorkspaceStageModel.RAWLS_WORKSPACE.toString()));
  }

  @Test
  public void createWorkspace_policyRejectedIfTpsDisabled_throws501() throws Exception {
    // Disable TPS feature flag for this test only
    when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(false);

    ApiErrorReport errorReport =
        createRawlsWorkspaceWithPolicyExpectError(HttpStatus.SC_NOT_IMPLEMENTED);
    assertTrue(errorReport.getMessage().contains("enabled"));
  }

  @Test
  public void updateWorkspace() throws Exception {
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);

    // Update workspace
    String newUserFacingId = "new-ufid";
    String newDisplayName = "new workspace display name";
    String newDescription = "new description for the workspace";
    ApiWorkspaceDescription updatedWorkspace =
        mockMvcUtils.updateWorkspace(
            USER_REQUEST, workspace.getId(), newUserFacingId, newDisplayName, newDescription);

    // Assert updated workspace
    mockMvcUtils.assertWorkspace(
        updatedWorkspace,
        newUserFacingId,
        newDisplayName,
        newDescription,
        /*expectedCreatedByEmail=*/ USER_REQUEST.getEmail(),
        /*expectedLastUpdatedByEmail=*/ USER_REQUEST.getEmail());

    // As second user, update only description
    String secondUserEmail = "foo@gmail.com";
    var newUser = new UserStatusInfo().userEmail(secondUserEmail).userSubjectId("foo");
    when(mockSamService().getUserStatusInfo(any())).thenReturn(newUser);
    var secondNewDescription = "This is yet another description";
    ApiWorkspaceDescription secondUpdatedWorkspace =
        mockMvcUtils.updateWorkspace(
            USER_REQUEST,
            workspace.getId(),
            /*newUserFacingId=*/ null,
            /*newDisplayName=*/ null,
            secondNewDescription);

    // Assert description is updated, while ufId and displayName are the same
    mockMvcUtils.assertWorkspace(
        secondUpdatedWorkspace,
        newUserFacingId,
        newDisplayName,
        secondNewDescription,
        /*expectedCreatedByEmail=*/ USER_REQUEST.getEmail(),
        /*expectedLastUpdatedByEmail=*/ secondUserEmail);

    // Assert second updated workspace's dates, in relation to first updated workspace
    assertEquals(secondUpdatedWorkspace.getCreatedDate(), updatedWorkspace.getCreatedDate());
    assertTrue(
        secondUpdatedWorkspace.getLastUpdatedDate().isAfter(updatedWorkspace.getLastUpdatedDate()));
  }

  @Test
  public void deleteWorkspaceProperties() throws Exception {
    // Create workspace with 4 properties: terra-type=type,
    // terra-workspace-short-description=short description, terra-workspace-version=version 3
    // userkey=uservalue
    UUID workspaceId = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST).getId();

    // Delete terra-type, userkey properties
    deleteWorkspaceProperties(workspaceId, List.of(Properties.TYPE, "userkey"));

    // Assert remaining 2 properties
    ApiWorkspaceDescription gotWorkspace = mockMvcUtils.getWorkspace(USER_REQUEST, workspaceId);
    mockMvcUtils.assertProperties(
        List.of(SHORT_DESCRIPTION_PROPERTY, VERSION_PROPERTY), gotWorkspace.getProperties());
  }

  @Test
  public void updateWorkspaceProperties() throws Exception {
    // Create workspace with 4 properties: terra-type=type,
    // terra-workspace-short-description=short description, terra-workspace-version=version 3
    // userkey=uservalue
    UUID workspaceId = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST).getId();

    // Change userkey value to uservalue2. Add new property foo=bar.
    ApiProperty newUserProperty = new ApiProperty().key("userkey").value("uservalue2");
    ApiProperty fooProperty = new ApiProperty().key("foo").value("bar");
    updateWorkspaceProperties(workspaceId, List.of(newUserProperty, fooProperty));

    // Assert 5 properties.
    ApiWorkspaceDescription gotWorkspace = mockMvcUtils.getWorkspace(USER_REQUEST, workspaceId);
    mockMvcUtils.assertProperties(
        List.of(
            SHORT_DESCRIPTION_PROPERTY,
            VERSION_PROPERTY,
            TYPE_PROPERTY,
            newUserProperty,
            fooProperty),
        gotWorkspace.getProperties());
  }

  @Test
  public void cloneWorkspace() throws Exception {
    // Disable TPS feature flag for this test
    when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(false);

    UUID workspaceId = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST).getId();
    ApiWorkspaceDescription sourceWorkspace = mockMvcUtils.getWorkspace(USER_REQUEST, workspaceId);

    ApiCloneWorkspaceResult cloneWorkspace =
        mockMvcUtils.cloneWorkspace(USER_REQUEST, workspaceId, FAKE_SPEND_PROFILE, null);

    UUID destinationWorkspaceId = cloneWorkspace.getWorkspace().getDestinationWorkspaceId();
    ApiWorkspaceDescription destinationWorkspace =
        mockMvcUtils.getWorkspace(USER_REQUEST, destinationWorkspaceId);

    assertEquals(sourceWorkspace.getProperties(), destinationWorkspace.getProperties());
    assertEquals(
        sourceWorkspace.getDisplayName() + " (Copy)", destinationWorkspace.getDisplayName());
  }

  @Test
  public void cloneWorkspace_rawls() throws Exception {
    UUID sourceWorkspaceId =
        mockMvcUtils
            .createWorkspaceWithoutCloudContext(
                USER_REQUEST, ApiWorkspaceStageModel.RAWLS_WORKSPACE)
            .getId();

    // Create some data repo references
    ApiDataRepoSnapshotResource snap1 =
        mockMvcUtils.createDataRepoSnapshotReference(USER_REQUEST, sourceWorkspaceId);
    ApiDataRepoSnapshotResource snap2 =
        mockMvcUtils.createDataRepoSnapshotReference(USER_REQUEST, sourceWorkspaceId);
    ApiDataRepoSnapshotResource snap3 =
        mockMvcUtils.createDataRepoSnapshotReference(
            USER_REQUEST,
            sourceWorkspaceId,
            new ApiCreateDataRepoSnapshotReferenceRequestBody()
                .metadata(
                    new ApiReferenceResourceCommonFields()
                        .cloningInstructions(ApiCloningInstructionsEnum.NOTHING)
                        .description("description")
                        .name(RandomStringUtils.randomAlphabetic(10)))
                .snapshot(
                    new ApiDataRepoSnapshotAttributes()
                        .instanceName("terra")
                        .snapshot("polaroid")));

    // Clone the rawls workspace into a destination rawls workspace
    // This relies on the mocked Sam check
    UUID destinationWorkspaceId = UUID.randomUUID();

    ApiCloneWorkspaceResult cloneWorkspace =
        mockMvcUtils.cloneWorkspace(
            USER_REQUEST, sourceWorkspaceId, FAKE_SPEND_PROFILE, destinationWorkspaceId);

    List<ApiResourceCloneDetails> cloneDetails = cloneWorkspace.getWorkspace().getResources();
    assertEquals(3, cloneDetails.size());
    List<UUID> cloneIdList =
        cloneDetails.stream().map(ApiResourceCloneDetails::getSourceResourceId).toList();
    assertThat(
        cloneIdList,
        containsInAnyOrder(
            snap1.getMetadata().getResourceId(),
            snap2.getMetadata().getResourceId(),
            snap3.getMetadata().getResourceId()));
    for (var cloneDetail : cloneDetails) {
      if (cloneDetail.getSourceResourceId().equals(snap3.getMetadata().getResourceId())) {
        assertEquals(ApiCloneResourceResult.SKIPPED, cloneDetail.getResult());
        assertNull(cloneDetail.getDestinationResourceId());
      } else {
        assertEquals(ApiCloneResourceResult.SUCCEEDED, cloneDetail.getResult());
        assertNotNull(cloneDetail.getDestinationResourceId());
      }
    }
  }

  @Test
  public void getWorkspace_includesPolicy() throws Exception {
    // No need to actually pass policy inputs because TPS is mocked.
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);

    ApiTpsPaoGetResult getPolicyResult =
        emptyWorkspacePao()
            .objectId(workspace.getId())
            .attributes(new ApiTpsPolicyInputs().addInputsItem(GROUP_POLICY))
            .effectiveAttributes(new ApiTpsPolicyInputs().addInputsItem(GROUP_POLICY));
    when(mockTpsApiDispatch().getPaoIfExists(any(), eq(workspace.getId())))
        .thenReturn(Optional.of(getPolicyResult));

    ApiWorkspaceDescription gotWorkspace =
        mockMvcUtils.getWorkspace(USER_REQUEST, workspace.getId());
    assertEquals(1, gotWorkspace.getPolicies().size());
    assertEquals(GROUP_POLICY, gotWorkspace.getPolicies().get(0));
  }

  @Test
  public void getWorkspace_tpsDisabled_excludesPolicy() throws Exception {
    when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(false);
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);

    ApiWorkspaceDescription gotWorkspace =
        mockMvcUtils.getWorkspace(USER_REQUEST, workspace.getId());
    assertNull(gotWorkspace.getPolicies());
  }

  @Test
  public void listWorkspace_includesPolicy() throws Exception {
    // No need to actually pass policy inputs because TPS is mocked.
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);
    ApiCreatedWorkspace noPolicyWorkspace =
        mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);
    when(mockSamService().listWorkspaceIdsAndHighestRoles(any(), any()))
        .thenReturn(
            ImmutableMap.of(
                workspace.getId(), WsmIamRole.OWNER, noPolicyWorkspace.getId(), WsmIamRole.OWNER));

    ApiTpsPaoGetResult getPolicyResult =
        new ApiTpsPaoGetResult()
            .attributes(new ApiTpsPolicyInputs().addInputsItem(GROUP_POLICY))
            .effectiveAttributes(new ApiTpsPolicyInputs().addInputsItem(GROUP_POLICY))
            .component(ApiTpsComponent.WSM)
            .objectType(ApiTpsObjectType.WORKSPACE)
            .objectId(workspace.getId())
            .sourcesObjectIds(Collections.emptyList());

    // Return a policy object for the first workspace
    when(mockTpsApiDispatch().getPaoIfExists(any(), eq(workspace.getId())))
        .thenReturn(Optional.of(getPolicyResult));
    // Treat the second workspace like it was created before policy existed and doesn't have a PAO
    when(mockTpsApiDispatch().getPaoIfExists(any(), eq(noPolicyWorkspace.getId())))
        .thenReturn(Optional.empty());

    ApiWorkspaceDescription gotWorkspace =
        mockMvcUtils.getWorkspace(USER_REQUEST, workspace.getId());
    assertEquals(1, gotWorkspace.getPolicies().size());
    assertEquals(GROUP_POLICY, gotWorkspace.getPolicies().get(0));
    ApiWorkspaceDescription gotNoPolicyWorkspace =
        getWorkspaceDescriptionFromList(noPolicyWorkspace.getId());
    assertTrue(gotNoPolicyWorkspace.getPolicies().isEmpty());
  }

  @Test
  public void listWorkspace_tpsDisabled_excludesPolicy() throws Exception {
    when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(false);
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);
    when(mockSamService().listWorkspaceIdsAndHighestRoles(any(), any()))
        .thenReturn(ImmutableMap.of(workspace.getId(), WsmIamRole.OWNER));

    ApiWorkspaceDescription gotWorkspace =
        mockMvcUtils.getWorkspace(USER_REQUEST, workspace.getId());
    assertNull(gotWorkspace.getPolicies());
  }

  @Test
  public void updatePolicies_tpsDisabled_throws501() throws Exception {
    when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(false);
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);

    updatePoliciesExpect(workspace.getId(), HttpStatus.SC_NOT_IMPLEMENTED);
  }

  @Test
  public void updatePolicies_tpsEnabledAndPolicyUpdated_log() throws Exception {
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);
    when(mockTpsApiDispatch().updatePao(any(), eq(workspace.getId()), any()))
        .thenReturn(new ApiTpsPaoUpdateResult().updateApplied(true));
    OffsetDateTime lastChangedDate =
        workspaceActivityLogDao.getLastUpdateDetails(workspace.getId()).get().getChangeDate();

    ApiTpsPaoUpdateResult result = updatePolicies(workspace.getId());
    assertTrue(result.isUpdateApplied());
    assertTrue(
        lastChangedDate.isBefore(
            workspaceActivityLogDao.getLastUpdateDetails(workspace.getId()).get().getChangeDate()));
  }

  @Test
  public void updatePolicies_tpsEnabledAndPolicyNotUpdated_notLog() throws Exception {
    ApiCreatedWorkspace workspace = mockMvcUtils.createWorkspaceWithoutCloudContext(USER_REQUEST);
    when(mockTpsApiDispatch().updatePao(any(), eq(workspace.getId()), any()))
        .thenReturn(new ApiTpsPaoUpdateResult().updateApplied(false));
    OffsetDateTime lastChangedDate =
        workspaceActivityLogDao.getLastUpdateDetails(workspace.getId()).get().getChangeDate();

    ApiTpsPaoUpdateResult result = updatePolicies(workspace.getId());
    assertFalse(result.isUpdateApplied());
    assertTrue(
        lastChangedDate.isEqual(
            workspaceActivityLogDao.getLastUpdateDetails(workspace.getId()).get().getChangeDate()));
  }

  private ApiErrorReport createRawlsWorkspaceWithPolicyExpectError(int expectedCode)
      throws Exception {
    ApiTpsPolicyInputs policyInputs =
        new ApiTpsPolicyInputs()
            .addInputsItem(new ApiTpsPolicyInput().namespace("terra").name("group-constraint"));
    return mockMvcUtils.createWorkspaceWithoutCloudContextExpectError(
        USER_REQUEST,
        /*workspaceId=*/ UUID.randomUUID(),
        ApiWorkspaceStageModel.RAWLS_WORKSPACE,
        policyInputs,
        expectedCode);
  }

  private void updateWorkspaceProperties(UUID workspaceId, List<ApiProperty> properties)
      throws Exception {
    ApiProperties apiProperties = new ApiProperties();
    apiProperties.addAll(properties);
    mockMvc
        .perform(
            addAuth(
                post(String.format(UPDATE_WORKSPACES_V1_PROPERTIES_PATH_FORMAT, workspaceId))
                    .contentType(MediaType.APPLICATION_JSON_VALUE)
                    .accept(MediaType.APPLICATION_JSON)
                    .characterEncoding("UTF-8")
                    .content(objectMapper.writeValueAsString(apiProperties)),
                USER_REQUEST))
        .andExpect(status().is(HttpStatus.SC_NO_CONTENT));
  }

  private void deleteWorkspaceProperties(UUID workspaceId, List<String> propertyKeys)
      throws Exception {
    ApiPropertyKeys apiPropertyKeys = new ApiPropertyKeys();
    apiPropertyKeys.addAll(propertyKeys);
    mockMvc
        .perform(
            addAuth(
                patch(String.format(UPDATE_WORKSPACES_V1_PROPERTIES_PATH_FORMAT, workspaceId))
                    .contentType(MediaType.APPLICATION_JSON_VALUE)
                    .accept(MediaType.APPLICATION_JSON)
                    .characterEncoding("UTF-8")
                    .content(objectMapper.writeValueAsString(apiPropertyKeys)),
                USER_REQUEST))
        .andExpect(status().is(HttpStatus.SC_NO_CONTENT));
  }

  /**
   * Similar to getWorkspaceDescription, but call the ListWorkspaces endpoint instead of the
   * GetWorkspace endpoint.
   */
  private ApiWorkspaceDescription getWorkspaceDescriptionFromList(UUID id) throws Exception {
    String serializedResponse =
        mockMvc
            .perform(addJsonContentType(addAuth(get(WORKSPACES_V1_PATH), USER_REQUEST)))
            .andExpect(status().is(HttpStatus.SC_OK))
            .andReturn()
            .getResponse()
            .getContentAsString();
    ApiWorkspaceDescriptionList workspaceDescriptionList =
        objectMapper.readValue(serializedResponse, ApiWorkspaceDescriptionList.class);
    return workspaceDescriptionList.getWorkspaces().stream()
        .filter(w -> w.getId().equals(id))
        .findFirst()
        .orElseThrow(() -> new RuntimeException("workspace " + id + "not found in list!"));
  }

  private ApiTpsPaoUpdateResult updatePolicies(UUID workspaceId) throws Exception {
    var serializedResponse =
        updatePoliciesExpect(workspaceId, HttpStatus.SC_OK)
            .andReturn()
            .getResponse()
            .getContentAsString();
    return objectMapper.readValue(serializedResponse, ApiTpsPaoUpdateResult.class);
  }

  private ResultActions updatePoliciesExpect(UUID workspaceId, int code) throws Exception {
    ApiTpsPaoUpdateRequest updateRequest =
        new ApiTpsPaoUpdateRequest()
            .updateMode(ApiTpsUpdateMode.ENFORCE_CONFLICT)
            .addAttributes(
                new ApiTpsPolicyInputs()
                    .addInputsItem(
                        new ApiTpsPolicyInput()
                            .namespace("terra")
                            .name("region-constraint")
                            .addAdditionalDataItem(
                                new ApiTpsPolicyPair().key("foo").value("bar"))));
    return mockMvc
        .perform(
            addAuth(
                patch(String.format(UPDATE_WORKSPACES_V1_POLICIES_PATH_FORMAT, workspaceId))
                    .contentType(MediaType.APPLICATION_JSON_VALUE)
                    .accept(MediaType.APPLICATION_JSON)
                    .characterEncoding("UTF-8")
                    .content(objectMapper.writeValueAsString(updateRequest)),
                USER_REQUEST))
        .andExpect(status().is(code));
  }
}