001/* 002 * (C) Copyright 2017 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bdelbosc 018 */ 019package org.nuxeo.ecm.platform.importer.mqueues.pattern; 020 021import java.io.IOException; 022import java.io.ObjectInput; 023import java.io.ObjectOutput; 024import java.util.Arrays; 025import java.util.Objects; 026 027/** 028 * Simple key value message. 029 * 030 * @since 9.1 031 */ 032public class keyValueMessage implements Message { 033 // Externalizable do rely on serialVersionUID 034 static final long serialVersionUID = 20170529L; 035 public static final keyValueMessage POISON_PILL = new keyValueMessage("_POISON_PILL_", null, true, false); 036 037 private String key; 038 private byte[] value; 039 private boolean poisonPill = false; 040 private boolean forceBatch = false; 041 042 public keyValueMessage() { 043 } 044 045 protected keyValueMessage(String key, byte[] value, boolean poisonPill, boolean forceBatch) { 046 this.key = Objects.requireNonNull(key); 047 this.value = value; 048 this.poisonPill = poisonPill; 049 this.forceBatch = forceBatch; 050 } 051 052 static public keyValueMessage of(String key, byte[] value) { 053 return new keyValueMessage(key, value, false, false); 054 } 055 056 static public keyValueMessage of(String key) { 057 return new keyValueMessage(key, null, false, false); 058 } 059 060 /** 061 * A message that force the batch. 062 */ 063 static public keyValueMessage ofForceBatch(String key, byte[] value) { 064 return new keyValueMessage(key, value, false, true); 065 } 066 067 static public keyValueMessage ofForceBatch(String key) { 068 return new keyValueMessage(key, null, false, true); 069 } 070 071 public String key() { 072 return key; 073 } 074 075 public byte[] value() { 076 return value; 077 } 078 079 @Override 080 public String getId() { 081 return key; 082 } 083 084 @Override 085 public boolean poisonPill() { 086 return poisonPill; 087 } 088 089 @Override 090 public boolean forceBatch() { 091 return forceBatch; 092 } 093 094 @Override 095 public void writeExternal(ObjectOutput out) throws IOException { 096 out.writeObject(key); 097 out.writeBoolean(poisonPill); 098 out.writeBoolean(forceBatch); 099 if (value == null || value.length == 0) { 100 out.writeInt(0); 101 } else { 102 out.writeInt(value.length); 103 out.write(value); 104 } 105 } 106 107 @Override 108 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 109 this.key = (String) in.readObject(); 110 this.poisonPill = in.readBoolean(); 111 this.forceBatch = in.readBoolean(); 112 int dataLength = in.readInt(); 113 if (dataLength == 0) { 114 this.value = null; 115 } else { 116 this.value = new byte[dataLength]; 117 // not using in.readFully because it is not impl by Chronicle WireObjectInput 118 int pos = 0; 119 while (pos < dataLength) { 120 pos += in.read(this.value, pos, dataLength - pos); 121 } 122 } 123 } 124 125 @Override 126 public boolean equals(Object o) { 127 if (this == o) return true; 128 if (o == null || getClass() != o.getClass()) return false; 129 130 keyValueMessage keyValueMessage = (keyValueMessage) o; 131 132 if (poisonPill != keyValueMessage.poisonPill) return false; 133 if (forceBatch != keyValueMessage.forceBatch) return false; 134 return key != null ? key.equals(keyValueMessage.key) : keyValueMessage.key == null; 135 136 } 137 138 @Override 139 public int hashCode() { 140 int result = key.hashCode(); 141 result = 31 * result + Arrays.hashCode(value); 142 result = 31 * result + (poisonPill ? 1 : 0); 143 result = 31 * result + (forceBatch ? 1 : 0); 144 return result; 145 } 146 147 @Override 148 public String toString() { 149 return String.format("keyValueMessage(\"%s\", len:%d%s%s)", key, (value != null) ? value.length : 0, 150 poisonPill ? ", poison" : "", forceBatch ? ", batch" : ""); 151 } 152}