Author: aadamchik
Date: Wed Nov 10 15:35:39 2010
New Revision: 1033520

URL: http://svn.apache.org/viewvc?rev=1033520&view=rev
Log:
Introdicung standard referenceable mixin

also implementing fine-grained versioning of the project to avoid including it 
as a SNAPSHOT

Added:
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/Referenceable.java
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/UuidCoder.java
    cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/
    cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/
    cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/
    cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/
    cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/ref/
    
cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/ref/UuidCoderTest.java
Modified:
    cayenne/sandbox/cayenne-mixin/branches/3.0/.classpath
    
cayenne/sandbox/cayenne-mixin/branches/3.0/.settings/org.eclipse.jdt.core.prefs
    cayenne/sandbox/cayenne-mixin/branches/3.0/pom.xml

Modified: cayenne/sandbox/cayenne-mixin/branches/3.0/.classpath
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/.classpath?rev=1033520&r1=1033519&r2=1033520&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/branches/3.0/.classpath (original)
+++ cayenne/sandbox/cayenne-mixin/branches/3.0/.classpath Wed Nov 10 15:35:39 
2010
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="src" output="target/classes" 
path="src/main/java"/>
+       <classpathentry kind="src" output="target/test-classes" 
path="src/test/java"/>
        <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
        <classpathentry kind="con" 
path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
        <classpathentry kind="output" path="target/classes"/>

Modified: 
cayenne/sandbox/cayenne-mixin/branches/3.0/.settings/org.eclipse.jdt.core.prefs
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/.settings/org.eclipse.jdt.core.prefs?rev=1033520&r1=1033519&r2=1033520&view=diff
==============================================================================
--- 
cayenne/sandbox/cayenne-mixin/branches/3.0/.settings/org.eclipse.jdt.core.prefs 
(original)
+++ 
cayenne/sandbox/cayenne-mixin/branches/3.0/.settings/org.eclipse.jdt.core.prefs 
Wed Nov 10 15:35:39 2010
@@ -1,6 +1,13 @@
-#Tue Nov 09 16:14:31 EST 2010
+#Tue Nov 09 16:45:36 EST 2010
 eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.6

Modified: cayenne/sandbox/cayenne-mixin/branches/3.0/pom.xml
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/pom.xml?rev=1033520&r1=1033519&r2=1033520&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/branches/3.0/pom.xml (original)
+++ cayenne/sandbox/cayenne-mixin/branches/3.0/pom.xml Wed Nov 10 15:35:39 2010
@@ -8,9 +8,13 @@
                <version>3.0.1</version>
        </parent>
        <artifactId>cayenne-mixin</artifactId>
-       <version>3.0.1</version>
+       <version>3.0.0.1</version>
        <name>Library: cayenne-mixin</name>
        <packaging>jar</packaging>
+       <properties>
+               <cayenne.version>3.0.1</cayenne.version>
+               <mockito.version>1.8.5</mockito.version>
+       </properties>
        <dependencies>
                <dependency>
                        <groupId>junit</groupId>
@@ -19,7 +23,13 @@
                <dependency>
                        <groupId>org.apache.cayenne</groupId>
                        <artifactId>cayenne-server</artifactId>
-                       <version>${version}</version>
+                       <version>${cayenne.version}</version>
+               </dependency>
+               <dependency>
+                               <groupId>org.mockito</groupId>
+                               <artifactId>mockito-all</artifactId>
+                               <version>${mockito.version}</version>
+                               <scope>test</scope>
                </dependency>
        </dependencies>
        <build>
@@ -29,8 +39,8 @@
                                        
<groupId>org.apache.maven.plugins</groupId>
                                        
<artifactId>maven-compiler-plugin</artifactId>
                                        <configuration>
-                                               <source>1.5</source>
-                                               <target>1.5</target>
+                                               <source>1.6</source>
+                                               <target>1.6</target>
                                        </configuration>
                                </plugin>
                        </plugins>

Added: 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/Referenceable.java
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/Referenceable.java?rev=1033520&view=auto
==============================================================================
--- 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/Referenceable.java
 (added)
+++ 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/Referenceable.java
 Wed Nov 10 15:35:39 2010
@@ -0,0 +1,43 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.apache.cayenne.mixin.ref;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A built-in mixin annotation that results in a UUID property being injected
+ * into annotated DataObject.
+ */
+...@target( { ElementType.TYPE })
+...@retention(RetentionPolicy.RUNTIME)
+...@documented
+...@inherited
+public @interface Referenceable {
+
+       /**
+        * A name of UUID property injected into a DataObject, making it
+        * referenceable.
+        */
+       public final String UUID_PROPERTY = "cayenne:uuid";
+}

Added: 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java?rev=1033520&view=auto
==============================================================================
--- 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java
 (added)
+++ 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java
 Wed Nov 10 15:35:39 2010
@@ -0,0 +1,126 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.apache.cayenne.mixin.ref;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.DataObject;
+import org.apache.cayenne.DataObjectUtils;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.LifecycleEvent;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.mixin.MixinHandler;
+import org.apache.cayenne.reflect.LifecycleCallbackRegistry;
+
+/**
+ * A {...@link MixinHandler} that injects {...@link 
Referenceable#UUID_PROPERTY} into
+ * DataObjects and provides methods to lookup objects by UUID, as well as read
+ * UUID of the existing objects.
+ */
+public class ReferenceableHandler implements MixinHandler<Referenceable> {
+
+       protected EntityResolver entityResolver;
+       protected Map<String, UuidCoder> coders;
+
+       public ReferenceableHandler(EntityResolver entityResolver) {
+               this.entityResolver = entityResolver;
+               this.coders = new HashMap<String, UuidCoder>();
+       }
+
+       /**
+        * Returns a Referenceable object matching provided UUID and bound in
+        * provided {...@link ObjectContext}.
+        */
+       public Object getReferenceable(ObjectContext context, String uuid) {
+
+               int separator = uuid.indexOf(':');
+               if (separator <= 0 || separator == uuid.length() - 1) {
+                       throw new IllegalArgumentException("Invalid uuid: " + 
uuid);
+               }
+
+               String entityName = uuid.substring(0, separator);
+               UuidCoder coder = coders.get(entityName);
+               if (coder == null) {
+                       throw new IllegalArgumentException("Entity " + 
entityName
+                                       + " is not a known referenceable");
+               }
+
+               ObjectId oid = coder.toObjectId(uuid.substring(separator + 1));
+               return DataObjectUtils.objectForPK(context, oid);
+       }
+
+       public String getUuid(Object referenceable) {
+
+               if (referenceable == null) {
+                       throw new NullPointerException("Null object");
+               }
+
+               if (referenceable instanceof DataObject) {
+
+                       // even if this is not a registered Referenceable, 
don't see a
+                       // problem if we return a UUID.
+                       DataObject dataObject = (DataObject) referenceable;
+                       String uuid = (String) dataObject
+                                       
.readPropertyDirectly(Referenceable.UUID_PROPERTY);
+
+                       if (uuid == null) {
+                               throw new IllegalArgumentException(
+                                               "No UUID set, is this a NEW or 
TRANSIENT object?");
+                       }
+
+                       return uuid;
+               } else {
+                       throw new IllegalArgumentException("Object is not a 
DataObject: "
+                                       + referenceable.getClass().getName());
+               }
+       }
+
+       @Override
+       public Class<Referenceable> getMixinType() {
+               return Referenceable.class;
+       }
+
+       @Override
+       public void setupListeners(LifecycleCallbackRegistry registry,
+                       Class<? extends DataObject> entityType) {
+
+               ObjEntity entity = entityResolver.lookupObjEntity(entityType);
+               coders.put(entity.getName(), new UuidCoder(entity));
+
+               registry.addListener(LifecycleEvent.POST_PERSIST, entityType, 
this,
+                               "initProperties");
+               registry.addListener(LifecycleEvent.POST_LOAD, entityType, this,
+                               "initProperties");
+       }
+
+       protected void initProperties(DataObject object) {
+               UuidCoder coder = 
coders.get(object.getObjectId().getEntityName());
+               if (coder == null) {
+                       throw new IllegalArgumentException("Entity "
+                                       + object.getObjectId().getEntityName()
+                                       + " is not a known referenceable");
+               }
+
+               String uuid = coder.toUuid(object.getObjectId());
+               object.writePropertyDirectly(Referenceable.UUID_PROPERTY, uuid);
+       }
+}

Added: 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/UuidCoder.java
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/UuidCoder.java?rev=1033520&view=auto
==============================================================================
--- 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/UuidCoder.java
 (added)
+++ 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/main/java/org/apache/cayenne/mixin/ref/UuidCoder.java
 Wed Nov 10 15:35:39 2010
@@ -0,0 +1,196 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.apache.cayenne.mixin.ref;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.util.Util;
+
+/**
+ * An object to encode/decode persistent objects UUIDs.
+ */
+class UuidCoder {
+
+       static final String UUID_SEPARATOR = ":";
+
+       private String entityName;
+       private SortedMap<String, Converter> converters;
+       private int idSize;
+
+       UuidCoder(ObjEntity entity) {
+
+               this.entityName = entity.getName();
+               this.converters = new TreeMap<String, Converter>();
+
+               for (ObjAttribute attribute : entity.getAttributes()) {
+                       if (attribute.isPrimaryKey()) {
+                               converters.put(attribute.getDbAttributeName(), 
create(attribute
+                                               .getJavaClass()));
+                       }
+               }
+
+               for (DbAttribute attribute : 
entity.getDbEntity().getPrimaryKeys()) {
+                       if (!converters.containsKey(attribute.getName())) {
+                               String type = TypesMapping
+                                               
.getJavaBySqlType(attribute.getType());
+                               try {
+                                       converters.put(attribute.getName(), 
create(Util
+                                                       .getJavaClass(type)));
+                               } catch (ClassNotFoundException e) {
+                                       throw new CayenneRuntimeException(
+                                                       "Can't instantiate 
class " + type, e);
+                               }
+                       }
+               }
+
+               if (converters.isEmpty()) {
+                       throw new IllegalArgumentException("Entity has no PK 
definied: "
+                                       + entity.getName());
+               }
+
+               this.idSize = (int) Math.ceil(converters.size() / 0.75d);
+       }
+
+       String toUuid(ObjectId id) {
+
+               if (id.isTemporary()) {
+                       throw new IllegalArgumentException(
+                                       "Can't create UUID for a temporary 
ObjectId");
+               }
+
+               Map<String, Object> idValues = id.getIdSnapshot();
+
+               StringBuilder buffer = new StringBuilder();
+               buffer.append(id.getEntityName());
+
+               for (Entry<String, Converter> entry : converters.entrySet()) {
+                       Object value = idValues.get(entry.getKey());
+                       buffer.append(UUID_SEPARATOR)
+                                       .append(entry.getValue().toUuid(value));
+               }
+
+               return buffer.toString();
+       }
+
+       ObjectId toObjectId(String uuidValues) {
+
+               // assume the caller already parsed out entity name and the 
argument is
+               // just concatenated ID values
+
+               if (converters.size() == 1) {
+                       Entry<String, Converter> entry = 
converters.entrySet().iterator()
+                                       .next();
+
+                       String decoded;
+                       try {
+                               decoded = URLDecoder.decode(uuidValues, 
"UTF-8");
+                       } catch (UnsupportedEncodingException e) {
+                               // unexpected
+                               throw new CayenneRuntimeException("Unsupported 
encoding", e);
+                       }
+                       return new ObjectId(entityName, entry.getKey(), 
entry.getValue()
+                                       .fromUuid(decoded));
+               }
+
+               Map<String, Object> idMap = new HashMap<String, Object>(idSize);
+               StringTokenizer toks = new StringTokenizer(uuidValues, 
UUID_SEPARATOR);
+
+               if (toks.countTokens() != converters.size()) {
+                       throw new IllegalArgumentException("Invalid UUID for 
entity "
+                                       + entityName + ": " + uuidValues);
+               }
+
+               for (Entry<String, Converter> entry : converters.entrySet()) {
+                       String value = toks.nextToken();
+
+                       String decoded;
+                       try {
+                               decoded = URLDecoder.decode(value, "UTF-8");
+                       } catch (UnsupportedEncodingException e) {
+                               // unexpected
+                               throw new CayenneRuntimeException("Unsupported 
encoding", e);
+                       }
+
+                       idMap.put(entry.getKey(), 
entry.getValue().fromUuid(decoded));
+               }
+
+               return new ObjectId(entityName, idMap);
+       }
+
+       private Converter create(Class<?> type) {
+
+               if (type == null) {
+                       throw new NullPointerException("Null type");
+               }
+
+               if (Long.class.isAssignableFrom(type)) {
+                       return new Converter() {
+                               @Override
+                               Object fromUuid(String uuid) {
+                                       return Long.valueOf(uuid);
+                               }
+                       };
+               } else if (Integer.class.isAssignableFrom(type)) {
+                       return new Converter() {
+                               @Override
+                               Object fromUuid(String uuid) {
+                                       return Integer.valueOf(uuid);
+                               }
+                       };
+               } else if (String.class.isAssignableFrom(type)) {
+                       return new Converter() {
+                               @Override
+                               Object fromUuid(String uuid) {
+                                       return uuid;
+                               }
+                       };
+               }
+
+               throw new IllegalArgumentException("Unsupported UUID type: "
+                               + type.getName());
+       }
+
+       abstract class Converter {
+
+               String toUuid(Object value) {
+                       try {
+                               return URLEncoder.encode(String.valueOf(value), 
"UTF-8");
+                       } catch (UnsupportedEncodingException e) {
+                               // unexpected
+                               throw new CayenneRuntimeException("Unsupported 
encoding", e);
+                       }
+               }
+
+               abstract Object fromUuid(String uuid);
+       }
+}

Added: 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/ref/UuidCoderTest.java
URL: 
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/ref/UuidCoderTest.java?rev=1033520&view=auto
==============================================================================
--- 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/ref/UuidCoderTest.java
 (added)
+++ 
cayenne/sandbox/cayenne-mixin/branches/3.0/src/test/java/org/apache/cayenne/mixin/ref/UuidCoderTest.java
 Wed Nov 10 15:35:39 2010
@@ -0,0 +1,137 @@
+package org.apache.cayenne.mixin.ref;
+
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class UuidCoderTest extends TestCase {
+
+       public void testSingleIntPk() {
+               DbEntity dbEntity = new DbEntity("X");
+               DbAttribute pk = new DbAttribute("ID");
+               pk.setType(Types.INTEGER);
+               pk.setPrimaryKey(true);
+               dbEntity.addAttribute(pk);
+
+               ObjEntity entity = mock(ObjEntity.class);
+               when(entity.getName()).thenReturn("x");
+               when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+               when(entity.getDbEntity()).thenReturn(dbEntity);
+
+               ObjectId id = new ObjectId("x", "ID", 3);
+
+               UuidCoder coder = new UuidCoder(entity);
+               assertEquals("x:3", coder.toUuid(id));
+
+               ObjectId parsedId = coder.toObjectId("3");
+               assertEquals(id, parsedId);
+       }
+
+       public void testSingleLongPk() {
+               DbEntity dbEntity = new DbEntity("X");
+               DbAttribute pk = new DbAttribute("ID");
+               pk.setType(Types.BIGINT);
+               pk.setPrimaryKey(true);
+               dbEntity.addAttribute(pk);
+
+               ObjEntity entity = mock(ObjEntity.class);
+               when(entity.getName()).thenReturn("x");
+               when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+               when(entity.getDbEntity()).thenReturn(dbEntity);
+
+               ObjectId id = new ObjectId("x", "ID", 3l);
+
+               UuidCoder coder = new UuidCoder(entity);
+               assertEquals("x:3", coder.toUuid(id));
+
+               ObjectId parsedId = coder.toObjectId("3");
+               assertEquals(id, parsedId);
+       }
+
+       public void testSingleStringPk() {
+               DbEntity dbEntity = new DbEntity("X");
+               DbAttribute pk = new DbAttribute("ID");
+               pk.setType(Types.VARCHAR);
+               pk.setPrimaryKey(true);
+               dbEntity.addAttribute(pk);
+
+               ObjEntity entity = mock(ObjEntity.class);
+               when(entity.getName()).thenReturn("x");
+               when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+               when(entity.getDbEntity()).thenReturn(dbEntity);
+
+               UuidCoder coder = new UuidCoder(entity);
+
+               ObjectId id = new ObjectId("x", "ID", "AbC");
+               assertEquals("x:AbC", coder.toUuid(id));
+
+               ObjectId parsedId = coder.toObjectId("AbC");
+               assertEquals(id, parsedId);
+       }
+
+       public void testIdEncoding() {
+               DbEntity dbEntity = new DbEntity("X");
+               DbAttribute pk = new DbAttribute("ID");
+               pk.setType(Types.VARCHAR);
+               pk.setPrimaryKey(true);
+               dbEntity.addAttribute(pk);
+
+               ObjEntity entity = mock(ObjEntity.class);
+               when(entity.getName()).thenReturn("x");
+               when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+               when(entity.getDbEntity()).thenReturn(dbEntity);
+
+               UuidCoder coder = new UuidCoder(entity);
+
+               ObjectId id = new ObjectId("x", "ID", "Ab:C");
+               assertEquals("x:Ab%3AC", coder.toUuid(id));
+
+               ObjectId parsedId = coder.toObjectId("Ab%3AC");
+               assertEquals(id, parsedId);
+       }
+
+       public void testMixedCompoundPk() {
+               DbEntity dbEntity = new DbEntity("X");
+               DbAttribute pk1 = new DbAttribute("ID");
+               pk1.setType(Types.VARCHAR);
+               pk1.setPrimaryKey(true);
+               dbEntity.addAttribute(pk1);
+
+               DbAttribute pk2 = new DbAttribute("ABC");
+               pk2.setType(Types.BIGINT);
+               pk2.setPrimaryKey(true);
+               dbEntity.addAttribute(pk2);
+
+               DbAttribute pk3 = new DbAttribute("ZZZ");
+               pk3.setType(Types.VARCHAR);
+               pk3.setPrimaryKey(true);
+               dbEntity.addAttribute(pk3);
+
+               ObjEntity entity = mock(ObjEntity.class);
+               when(entity.getName()).thenReturn("x");
+               when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+               when(entity.getDbEntity()).thenReturn(dbEntity);
+
+               UuidCoder coder = new UuidCoder(entity);
+
+               Map<String, Object> idMap = new HashMap<String, Object>();
+               idMap.put("ID", "X;Y");
+               idMap.put("ABC", 6783463l);
+               idMap.put("ZZZ", "'_'");
+               ObjectId id = new ObjectId("x", idMap);
+               assertEquals("x:6783463:X%3BY:%27_%27", coder.toUuid(id));
+               
+               ObjectId parsedId = coder.toObjectId("6783463:X%3BY:%27_%27");
+               assertEquals(id, parsedId);
+       }
+}


Reply via email to