7d39f48e0ccac61e95f813a4d0ea86f62a94db46
[controller.git] / opendaylight / md-sal / cds-access-api / src / main / java / org / opendaylight / controller / cluster / access / concepts / Envelope.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.access.concepts;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.MoreObjects;
13 import java.io.Externalizable;
14 import java.io.IOException;
15 import java.io.ObjectInput;
16 import java.io.ObjectOutput;
17 import java.io.Serializable;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.controller.cluster.access.ABIVersion;
20 import org.opendaylight.yangtools.concepts.Immutable;
21 import org.opendaylight.yangtools.concepts.WritableObjects;
22
23 public abstract class Envelope<T extends Message<?, ?>> implements Immutable, Serializable {
24     interface SerialForm<T extends Message<?, ?>, E extends Envelope<T>> extends Externalizable {
25
26         @NonNull E envelope();
27
28         void setEnvelope(@NonNull E envelope);
29
30         @java.io.Serial
31         Object readResolve();
32
33         @Override
34         default void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
35             final byte header = WritableObjects.readLongHeader(in);
36             final var sessionId = WritableObjects.readFirstLong(in, header);
37             final var txSequence = WritableObjects.readSecondLong(in, header);
38             @SuppressWarnings("unchecked")
39             final var message = (T) in.readObject();
40             setEnvelope(readExternal(in, sessionId, txSequence, message));
41         }
42
43         E readExternal(ObjectInput in, long sessionId, long txSequence, T message) throws IOException;
44
45         @Override
46         default void writeExternal(final ObjectOutput out) throws IOException {
47             writeExternal(out, envelope());
48         }
49
50         default void writeExternal(final ObjectOutput out, final @NonNull E envelope) throws IOException {
51             WritableObjects.writeLongs(out, envelope.getSessionId(), envelope.getTxSequence());
52             out.writeObject(envelope.getMessage());
53         }
54     }
55
56     @java.io.Serial
57     private static final long serialVersionUID = 1L;
58
59     private final @NonNull T message;
60     private final long txSequence;
61     private final long sessionId;
62
63     Envelope(final T message, final long sessionId, final long txSequence) {
64         this.message = requireNonNull(message);
65         this.sessionId = sessionId;
66         this.txSequence = txSequence;
67     }
68
69     /**
70      * Get the enclosed message.
71      *
72      * @return enclose message
73      */
74     public @NonNull T getMessage() {
75         return message;
76     }
77
78     /**
79      * Get the message transmission sequence of this envelope.
80      *
81      * @return Message sequence
82      */
83     public long getTxSequence() {
84         return txSequence;
85     }
86
87     /**
88      * Get the session identifier.
89      *
90      * @return Session identifier
91      */
92     public long getSessionId() {
93         return sessionId;
94     }
95
96     @Override
97     public String toString() {
98         return MoreObjects.toStringHelper(Envelope.class).add("sessionId", Long.toHexString(sessionId))
99                 .add("txSequence", Long.toHexString(txSequence)).add("message", message).toString();
100     }
101
102     @java.io.Serial
103     final Object writeReplace() {
104         return ABIVersion.MAGNESIUM.lt(message.getVersion()) ? createProxy() : legacyProxy();
105     }
106
107     abstract @NonNull SerialForm<T, ?> createProxy();
108
109     abstract @NonNull AbstractEnvelopeProxy<T, ?> legacyProxy();
110 }