summaryrefslogtreecommitdiff
path: root/same/src/main/java/com/orbekk/util/DelayedOperation.java
blob: caffa4f7b4c202dfabc4825b766d246e714366eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
 * Copyright 2012 Kjetil Ørbekk <kjetil.orbekk@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.orbekk.util;

import java.util.concurrent.CountDownLatch;

public class DelayedOperation {
    public static class Status {
        public final static int OK = 1;
        public final static int CONFLICT = 2;
        public final static int ERROR = 3;

        private int status;
        private String message;

        public static Status createOk() {
            return new Status(OK, "");
        }

        public static Status createConflict(String message) {
            return new Status(CONFLICT, message);
        }

        public static Status createError(String message) {
            return new Status(ERROR, message);
        }

        public Status(int status, String message) {
            this.status = status;
            this.message = message;
        }

        public boolean isOk() {
            return status == OK;
        }
        
        public boolean isError() {
            return status == ERROR;
        }
        
        public boolean isConflict() {
            return status == CONFLICT;
        }
        
        public boolean canRetry() {
            return isError();
        }
        
        public int getStatusCode() {
            return status;
        }
        
        public String getMessage() {
            return message;
        }
        
        @Override public String toString() {
            switch(status) {
            case OK:
                return "OK";
            case CONFLICT:
                return "Conflicting update: " + message;
            case ERROR:
                return "Error: " + message;
            }
            throw new AssertionError("Unhandled case.");
        }

        @Override public boolean equals(Object other) {
            if (!(other instanceof Status)) {
                return false;
            }
            Status o = (Status)other;
            if (o.status != this.status) {
                return false;
            }
            if (message == null) {
                return o.message == null;
            }
            return message.equals(o.message);
        }
    }

    private volatile Status status;
    private volatile int identifier;
    private final CountDownLatch done = new CountDownLatch(1);
    
    public DelayedOperation() {
    }

    public Status getStatus() {
        waitFor();
        return status;
    }

    public void waitFor() {
        try {
            done.await();
        } catch (InterruptedException e) {
            complete(new Status(Status.ERROR, "Thread interrupted."));
            Thread.currentThread().interrupt();
        }
    }

    public synchronized boolean isDone() {
        return done.getCount() <= 0;
    }

    public synchronized void complete(Status status) {
        this.status = status;
        done.countDown();
    }

    public synchronized int getIdentifier() {
        return identifier;
    }

    public synchronized void setIdentifier(int identifier) {
        this.identifier = identifier;
    }
}