/*
* Copyright 2010 Spolecne s.r.o. (www.spoledge.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.google.appengine.api.datastore;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
/**
* This is a GWT emulation class.
* It is ONLY used on the client side - JavaScript.
*
* This class is intended to use with custom DTO serializers
* generated by AuDAO.
*
* Method hashCode() may differ from the original one.
*/
public class Key implements Serializable, Comparable<Key> {
static final long serialVersionUID = -448150158203091507L;
private Key parentKey;
private String kind;
private long id;
private String name;
////////////////////////////////////////////////////////////////////////////
// Constructors
////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("unused")
private Key() {
}
Key( String kind, Key parentKey, long id, String name ) {
if (kind == null || kind.length() == 0)
throw new IllegalArgumentException("Kind cannot be empty");
if (name != null) {
if (name.length() == 0) throw new IllegalArgumentException("Name cannot be empty");
if (id != 0) throw new IllegalArgumentException("Cannot specify both id and name at once");
}
this.kind = kind;
this.parentKey = parentKey;
this.id = id;
this.name = name;
}
////////////////////////////////////////////////////////////////////////////
// Public
////////////////////////////////////////////////////////////////////////////
public String getKind() {
return kind;
}
public Key getParent() {
return parentKey;
}
public String getName() {
return name;
}
public long getId() {
return id;
}
public boolean isComplete() {
return name != null || id != 0;
}
public Key getChild( String kind, long id ) {
return new Key( kind, this, id, null );
}
public Key getChild( String kind, String name ) {
return new Key( kind, this, 0, name );
}
////////////////////////////////////////////////////////////////////////////
// Comparable
////////////////////////////////////////////////////////////////////////////
public int compareTo( Key o ) {
if (this == o) return 0;
Iterator<Key> path = reverse( this ).iterator();
Iterator<Key> oPath = reverse( o ).iterator();
while (path.hasNext()) {
Key key = path.next();
if (oPath.hasNext()) {
Key oKey = oPath.next();
int ret = compareToInternal( key, oKey );
if (ret != 0) return ret;
}
else {
return 1;
}
}
return oPath.hasNext() ? -1 : 0;
}
////////////////////////////////////////////////////////////////////////////
// Misc
////////////////////////////////////////////////////////////////////////////
public boolean equals( Object o ) {
if (this == o) return true;
if (o == null || (!(o instanceof Key))) return false;
Key k = (Key) o;
if ( id != k.id ) return false;
if ( !kind.equals( k.kind )) return false;
if ( name != null ) {
if ( !name.equals( k.name )) return false;
}
else {
if ( k.name != null ) return false;
if ( id == 0 ) return false; // incomplete keys are different
}
if ( parentKey != null ) {
if ( !parentKey.equals( k.parentKey )) return false;
}
else if ( k.parentKey != null ) return false;
return true;
}
public int hashCode() {
int ret = kind.hashCode();
if ( parentKey != null ) ret += parentKey.hashCode() * 29;
if (name != null) {
ret = 29 * ret + name.hashCode();
}
else {
ret = 29 * ret + (int)( id ^ (id >>> 32));
}
return ret;
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendToString( sb );
return sb.toString();
}
////////////////////////////////////////////////////////////////////////////
// Private
////////////////////////////////////////////////////////////////////////////
private void appendToString( StringBuilder sb ) {
if ( parentKey != null ) {
parentKey.appendToString( sb );
sb.append( '/' );
}
sb.append( kind );
sb.append( '(' );
if (name != null) sb.append('"').append( name ).append( '"' );
else sb.append( id );
sb.append( ')' );
}
private static ArrayList<Key> reverse( Key key ) {
ArrayList<Key> ret = key.getParent() != null ? reverse( key.getParent()) : new ArrayList<Key>();
ret.add( key );
return ret;
}
private static int compareToInternal( Key k1, Key k2 ) {
if (k1 == k2) return 0;
int ret = k1.getKind().compareTo( k2.getKind());
if (ret != 0) return ret;
if (k1.getId() != 0) {
if (k2.getId() == 0) return -1;
else return Long.valueOf( k1.getId()).compareTo( Long.valueOf( k2.getId()));
}
if (k2.getId() != 0) return 1;
if (k1.getName() != null) return k1.getName().compareTo(k2.getName());
return k2.getName() == null ? 0 : 1;
}
}
|