/*
* Copyright 2008-2009 LinkedIn, Inc
*
* 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 voldemort.serialization;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import voldemort.utils.Utils;
import com.google.common.base.Objects;
/**
* A SerializerDefinition holds all the meta information for a serializer.
*
*
*/
public class SerializerDefinition {
private final String name;
private final Integer currentSchemaVersion;
private final boolean hasVersion;
private final Map<Integer, String> schemaInfoByVersion;
private final Compression compression;
public SerializerDefinition(String name) {
super();
this.name = Utils.notNull(name);
this.currentSchemaVersion = -1;
this.schemaInfoByVersion = new HashMap<Integer, String>();
compression = null;
this.hasVersion = true;
}
public SerializerDefinition(String name, String schemaInfo) {
super();
this.name = Utils.notNull(name);
this.currentSchemaVersion = 0;
this.schemaInfoByVersion = new HashMap<Integer, String>();
this.schemaInfoByVersion.put(0, schemaInfo);
compression = null;
this.hasVersion = true;
}
public SerializerDefinition(String name,
Map<Integer, String> schemaInfos,
boolean hasVersion,
Compression compression) {
super();
this.name = Utils.notNull(name);
this.schemaInfoByVersion = new HashMap<Integer, String>();
this.compression = compression;
this.hasVersion = hasVersion;
if(!hasVersion) {
this.currentSchemaVersion = 0;
if(schemaInfos.size() != 1)
throw new IllegalArgumentException("Schema version = none, but multiple schemas specified.");
String schema = schemaInfos.values().iterator().next();
this.schemaInfoByVersion.put(0, schema);
} else {
int max = -1;
for(Integer key: schemaInfos.keySet()) {
if(key < 0)
throw new IllegalArgumentException("Version cannot be less than 0.");
else if(key > Byte.MAX_VALUE)
throw new IllegalArgumentException("Version cannot be more than "
+ Byte.MAX_VALUE);
if(key > max)
max = key;
this.schemaInfoByVersion.put(key, schemaInfos.get(key));
}
this.currentSchemaVersion = max;
}
}
public String getName() {
return name;
}
public int getCurrentSchemaVersion() {
if(currentSchemaVersion < 0)
throw new IllegalStateException("There is no schema info associated with this serializer definition.");
return currentSchemaVersion;
}
public Map<Integer, String> getAllSchemaInfoVersions() {
return this.schemaInfoByVersion;
}
public boolean hasSchemaInfo() {
return this.currentSchemaVersion >= 0;
}
public String getSchemaInfo(int version) {
if(!schemaInfoByVersion.containsKey(version))
throw new IllegalArgumentException("Unknown schema version " + version + ".");
return schemaInfoByVersion.get(version);
}
public String getCurrentSchemaInfo() {
if(currentSchemaVersion < 0)
throw new IllegalStateException("There is no schema info associated with this serializer definition.");
return schemaInfoByVersion.get(this.currentSchemaVersion);
}
public boolean hasVersion() {
return this.hasVersion;
}
public boolean hasCompression() {
return compression != null;
}
public Compression getCompression() {
return compression;
}
private boolean commonEquals(Object obj) {
if(obj == this)
return true;
if(obj == null)
return false;
if(!(obj.getClass() == SerializerDefinition.class))
return false;
SerializerDefinition s = (SerializerDefinition) obj;
return Objects.equal(getName(), s.getName())
&& Objects.equal(this.compression, s.compression)
&& this.hasVersion == s.hasVersion();
}
@Override
public boolean equals(Object obj) {
boolean isEqual = commonEquals(obj);
if(!isEqual) {
return false;
}
SerializerDefinition s = (SerializerDefinition) obj;
return Objects.equal(this.schemaInfoByVersion, s.schemaInfoByVersion);
}
public boolean semanticEquals(Object obj) {
boolean isEqual = commonEquals(obj);
if(!isEqual) {
return false;
}
/*
* The code seems like copy/paste from equals. But semanticEquals want
* to differentiate the false returned from
*
* commonEquals - something does not match, return false immediately
* schema map - String schema check does not match, try the Serializer
* comparison
*
* using equals method directly does not give the distinction and might
* return true, if the difference is only in the compression.
*/
SerializerDefinition other = (SerializerDefinition) obj;
if(Objects.equal(this.schemaInfoByVersion, other.schemaInfoByVersion))
return true;
// If the schema definition does not match as String, try to use the
// type comparison
Serializer serializer = new DefaultSerializerFactory().getSerializer(this);
Serializer otherSerializer = new DefaultSerializerFactory().getSerializer(other);
return Objects.equal(serializer, otherSerializer);
}
public String getFormattedString() {
StringBuilder sb = new StringBuilder();
sb.append("Type : " + name + "\n");
sb.append("LatestVersion : " + currentSchemaVersion + "\n");
for(Map.Entry<Integer, String> entry: schemaInfoByVersion.entrySet()) {
sb.append(" Version " + entry.getKey() + " : " + entry.getValue() + "\n");
}
sb.append(" Compression : " + compression + "\n");
sb.append(" VersionExists : " + hasVersion + "\n");
return sb.toString();
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[] { name, this.schemaInfoByVersion, compression,
hasVersion });
}
@Override
public String toString() {
return "SerializerDefinition(name = " + this.name + ", schema-info = "
+ this.schemaInfoByVersion + ", compression = " + compression + ")";
}
}